2015-05-01 18 views
18

Ben, ASP.NET 5 (vNext) değişiklikleri öğrenmek başlayan ve "Model" 'in yöntemine bildiğimIServiceProvider ASP.NET'te Çekirdek

public class Entity 
{ 
    public void DoSomething() 
    { 
      var dbContext = ServiceContainer.GetService<DataContext>(); //Where is ServiceContainer or something like that ? 
    } 
} 

örneğin, IServiceProvider nasıl bulamıyor Hizmete başlangıçta hizmet veriyoruz, ancak tüm servis koleksiyonları kalıyor ya da IServiceProvider kalıyor mu?

cevap

1

Hizmetinizi satır içi almak yerine, onu yapıcıya enjekte etmeyi deneyin.

public class Startup 
{ 
    public void ConfigureServices(IServiceCollection services) 
    { 
     services.AddTransient(typeof(DataContext)); 
    } 
} 

public class Entity 
{ 
    private DataContext _context; 

    public Entity(DataContext context) 
    { 
     _context = context; 
    } 

    public void DoSomething() 
    { 
     // use _context here 
    } 
} 

Ben de üzerinde önemli bir etkisi olacak gibi ne AddTransient araçlarla üzerinde okuma önermek nasıl DBContext sizin uygulama payları örnekleri. Bu, Dependency Injection adı verilen bir modeldir. Alışmak için biraz zaman alır, ama asla bir kez geri dönmek istemeyeceksin.

+0

sayesinde cevap için, ama eğer birçok varlığım varsa yeniden yazmam gerekiyor te kurucular ve yöntem argümanlar içinde enjeksiyon çirkin görünüyor kullanarak Activator.CreateInstance, kullanarak olamaz u YAGNI aşağıdaki bana iyi paterni söyleyebilir? – Sam

+0

Entity Framework'ü kullanmaya çalışıyor musunuz? Enjeksiyon, yöntemlerde değil, yapıcılarda kullanılır. Bu bağlamda YAGNI ile ne demek istediğinden emin değilim. – Anton

+0

Evet, Entity Framework'ü kullanıyorum, ancak şu durumda bakın: Örneğin, Katalog - ve Katalog'un var özelliği - Url, eski MVC'de sadece httpcontext sarmalayıcı oluşturabilir ve url helper özelliğini kullanarak , Yeni MVC'de Bunu yapamıyorum ve yöntemde IUrlHelper (özellik yolunda yeni yöntem sarıcı ekleyerek) DRY için 'u ekleyin, ancak bu hala çok garip – Sam

30

Sen Ayrıca doğrudan hizmet enjekte unutmayın

IServiceProvider 

kullanılmalıdır jenerik

GetService<T>(); 

uzatma yöntemine erişmek için Microsoft.Extensions.DependencyInjection ad alanında getirmek zorunda ASP.NET 5. denetleyicileri içine bakın. Aşağıdaki örneğe bakın.

public interface ISomeService 
{ 
    string ServiceValue { get; set; } 
} 

public class ServiceImplementation 
{ 
    public ServiceImplementation() 
    { 
     ServiceValue = "Injected from Startup"; 
    } 

    public string ServiceValue { get; set; } 
} 

Startup.cs

public void ConfigureService(IServiceCollection services) 
{ 
    ... 
    services.AddSingleton<ISomeService, ServiceImplementation>(); 
} 

HomeController

using Microsoft.Extensions.DependencyInjection; 
... 
public IServiceProvider Provider { get; set; } 
public ISomeService InjectedService { get; set; } 

public HomeController(IServiceProvider provider, ISomeService injectedService) 
{ 
    Provider = provider; 
    InjectedService = Provider.GetService<ISomeService>(); 
} 

Ya yaklaşım hizmetine erişmek için kullanılabilir. Ek hizmet için her zaman bir tane verilir. İlk nesne oluşturulmasından siz sorumlusunuz.

AddSingleton<IService, Service>() 

Tek bir örnek oluşturulur ve bir singleton gibi davranır.

AddTransient<IService, Service>() 

Her enjekte edildiğinde yeni bir örnek oluşturulur.

AddScoped<IService, Service>() 

Geçerli HTTP İsteği kapsamında tek bir örnek oluşturulur. Mevcut kapsam bağlamında Singleton'a eşdeğerdir.

Güncelleme 13 Ekim 2016

Bkz:

public class Entity 
{ 
    private readonly IDataContext dbContext; 

    // The DI will auto inject this for you 
    public class Entity(IDataContext dbContext) 
    { 
     this.dbContext = dbContext; 
    } 

    public void DoSomething() 
    { 
     // dbContext is already populated for you 
     var something = dbContext.Somethings.First(); 
    } 
} 

Ancak Entity olurdu: aspnet GitHub - ServiceCollectionServiceExtensions.cs

+1

Bu, OP ile ilgili olan ASP.NET 5'te çalışmamaktadır. Belki bir şey özlüyorum –

+0

Bu gönderiden beri değişti. Yanılmıyorsam, bu Beta 7'ninki miydi? Bu kesinlikle ASP.NET 5'e başvurmaktır. Microsoft.Framework.DependencyInjection adından Microsoft.Extensions.DependencyInjection ad alanına yeniden adlandırıldılar. Burada GetService uzantısının tanımlandığı yer: https://github.com/aspnet/DependencyInjection/blob/dev/src/Microsoft.Extensions.DependencyInjection.Abstractions/ServiceProviderExtensions.cs –

+0

Hmmm ... sadece denedim: DNX 4.6 'kullanarak Microsoft.Extensions.DependencyInjection; 've' GetService () '; hatayla sonuçlanır, 'GetService 'adı geçerli olan bağlamda mevcut değildir.' –

2

Genellikle DI onun şey ve sizin için enjekte sahip olmak istiyorum otomatik olarak sizin için örnek alınacak ...Controller veya ViewComponent gibi. Bu dbContext size mevcut olmadığı manuel bir yerden bu örneğini gerekiyorsa, o zaman bunu yapabilirsiniz:

using Microsoft.Extensions.PlatformAbstractions; 

public class Entity 
{ 
    private readonly IDataContext dbContext; 

    public class Entity() 
    { 
     this.dbContext = (IDataContext)CallContextServiceLocator.Locator.ServiceProvider 
          .GetService(typeof(IDataContext)); 
    } 

    public void DoSomething() 
    { 
     var something = dbContext.Somethings.First(); 
    } 
} 

Ama vurgulamak, bu bir anti-desen olarak kabul edilir ve kesinlikle sürece kaçınılmalıdır gerekli. Ve ... bazı model insanlar yapma riski çok üzülmüşse ... tüm diğerleri başarısız olursa, bir static IContainer bir yardımcı sınıf veya bir şey ekleyebilir ve ConfigureServices yönteminde StartUp sınıfına atayabilirsiniz: MyHelper.DIContainer = builder.Build(); Ve bu bir Bunu yapmak için gerçekten çirkin bir yol, ama bazen sadece işe almak gerekir.

3

Ben herhangi bir hizmet erişim için bir varlığın (veya bir model) için iyi bir fikir olduğunu sanmıyorum.

Kontrolörler, diğer taraftan, onların kurucularınızdaki herhangi bir kayıtlı hizmetine erişimi var ve bu konuda endişelenmenize gerek yoktur.

public class NotifyController : Controller 
{ 
    private static IEmailSender emailSender = null; 
    protected static ISessionService session = null; 
    protected static IMyContext dbContext = null; 
    protected static IHostingEnvironment hostingEnvironment = null; 

    public NotifyController(
       IEmailSender mailSenderService, 
       IMyContext context, 
       IHostingEnvironment env, 
       ISessionService sessionContext) 
    { 
     emailSender = mailSenderService; 
     dbContext = context; 
     hostingEnvironment = env; 
     session = sessionContext; 
    } 
} 
+0

Şimdi de bence :) – Sam

3

kullanımı GetRequiredService yerine GetService, ASP.NET 'Çekirdek kılavuzlar, örneğin yöntemine (https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/working-with-sql)

belgeleri gibi:

https://docs.microsoft.com/en-us/aspnet/core/api/microsoft.extensions.dependencyinjection.serviceproviderserviceextensions#Microsoft_Extensions_DependencyInjection_ServiceProviderServiceExtensions_GetRequiredService__1_System_IServiceProvider_

using Microsoft.Extensions.DependencyInjection; 

     using (var context = new ApplicationDbContext(serviceProvicer.GetRequiredService<DbContextOptions<ApplicationDbContext>>()))