ASP.NET Core中的IServiceProvider

我开始学习ASP.NET 5(vNext)中的更改,但无法找到如何获取IServiceProvider,例如在“Model”的方法中

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

我知道,我们在启动时配置服务,但所有服务集合停留在哪里或IServiceProvider?

您必须引入Microsoft.Extensions.DependencyInjection命名空间才能访问generics

 GetService(); 

应该使用的扩展方法

 IServiceProvider 

另请注意,您可以直接将服务注入ASP.NET 5中的控制器。请参阅下面的示例。

 public interface ISomeService { string ServiceValue { get; set; } } public class ServiceImplementation : ISomeService { public ServiceImplementation() { ServiceValue = "Injected from Startup"; } public string ServiceValue { get; set; } } 

Startup.cs

 public void ConfigureService(IServiceCollection services) { ... services.AddSingleton(); } 

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(); } 

这两种方法都可用于访问服务。 Startup.cs的附加服务扩展

 AddInstance(new Service()) 

一直有一个实例。 您负责初始对象创建。

 AddSingleton() 

创建单个实例,它就像一个单例。

 AddTransient() 

每次注入时都会创建一个新实例。

 AddScoped() 

在当前HTTP请求范围内创建单个实例。 它等效于当前范围上下文中的Singleton。

2018年10月18日更新

请参阅: aspnet GitHub – ServiceCollectionServiceExtensions.cs

我不认为实体(或模型)访问任何服务是个好主意。

另一方面,控制器可以访问其构造函数中的任何已注册服务,您不必担心它。

 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; } } 

使用GetRequiredService而不是GetService ,就像ASP.NET核心教程中的示例一样( https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/working-with-sql

有关方法的文档:

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>())) 

通常你想让DI做它的事情并为你注入:

 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(); } } 

但是, Entity必须自动为您实例化…如ControllerViewComponent 。 如果需要从无法使用此dbContext的位置手动实例化,则可以执行以下操作:

 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(); } } 

但只是要强调,这被认为是反模式,除非绝对必要,否则应该避免。 并且……冒着使某些模式让人感到沮丧的风险……如果所有其他方法都失败了,你可以在一个帮助器类或其他东西中添加一个static IContainer ,并在ConfigureServices方法的StartUp类中分配它: MyHelper.DIContainer = builder.Build(); 这是一个非常难看的方式,但有时你只需要让它工作。

不要让你的服务内联,尝试将其注入构造函数。

 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 } } 

我还建议阅读AddTransient含义,因为它会对您的应用程序如何共享DbContext的实例产生重大影响。 这是一种称为dependency injection的模式。 需要一段时间才能习惯,但是一旦你这样做,你将永远不想回去。