该IServiceCollection
接口用于构建依赖项注入容器。完全构建后,它将组成一个IServiceProvider
实例,您可以使用该实例来解析服务。您可以将注入IServiceProvider
到任何类中。的IApplicationBuilder
和HttpContext
类可以提供所述服务提供商以及经由其ApplicationServices
或RequestServices
分别性质。
IServiceProvider
定义一种GetService(Type type)
解决服务的方法:
var service = (IFooService)serviceProvider.GetService(typeof(IFooService));
还有一些便利的扩展方法可用,如serviceProvider.GetService<IFooService>()
(添加using
的Microsoft.Extensions.DependencyInjection
)。
在启动类中解析服务
注入依赖
运行时的托管服务提供程序可以将某些服务注入到Startup
类的构造函数中,例如IConfiguration
,
IWebHostEnvironment
(IHostingEnvironment
在3.0之前的版本中)ILoggerFactory
和IServiceProvider
。请注意,后者是由托管层构建的实例,并且仅包含用于启动应用程序的基本服务。
该ConfigureServices()
方法不允许注入服务,它仅接受一个IServiceCollection
参数。这是有道理的,因为ConfigureServices()
您可以在其中注册应用程序所需的服务。但是,您可以在此处使用注入启动程序构造函数中的服务,例如:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// Use Configuration here
}
ConfigureServices()
然后,可以将注册的任何服务注入该Configure()
方法;您可以在IApplicationBuilder
参数之后添加任意数量的服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IFooService>();
}
public void Configure(IApplicationBuilder app, IFooService fooService)
{
fooService.Bar();
}
手动解决依赖关系
如果您需要手动解决服务,你最好使用ApplicationServices
提供了通过IApplicationBuilder
在Configure()
方法:
public void Configure(IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}
可以IServiceProvider
在Startup
类的构造函数中直接传递in ,但是如上所述,这将包含services的有限子集,因此实用程序也受到限制:
public Startup(IServiceProvider serviceProvider)
{
var hostingEnv = serviceProvider.GetService<IWebHostEnvironment>();
}
如果必须使用该ConfigureServices()
方法解析服务,则需要使用其他方法。您可以IServiceProvider
从IServiceCollection
实例构建一个中间层,该中间层包含到那时为止已注册的服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IFooService, FooService>();
// Build the intermediate service provider
var sp = services.BuildServiceProvider();
// This will succeed.
var fooService = sp.GetService<IFooService>();
// This will fail (return null), as IBarService hasn't been registered yet.
var barService = sp.GetService<IBarService>();
}
请注意:
通常,您应该避免在ConfigureServices()
方法内部解析服务,因为实际上这是您配置应用程序服务的地方。有时您只需要访问一个IOptions<MyOptions>
实例。您可以通过将IConfiguration
实例中的值绑定到实例来实现此目的MyOptions
(本质上是选项框架所做的事情):
public void ConfigureServices(IServiceCollection services)
{
var myOptions = new MyOptions();
Configuration.GetSection("SomeSection").Bind(myOptions);
}
手动解决服务(又称为服务定位器)通常被认为是反模式。尽管有其用例(用于框架和/或基础结构层),但您应尽可能避免使用它。