转载请注明出处: https://home.cnblogs.com/u/zhiyong-ITNote/
整个asp.net core管道从WebHostBuilder到WebHost到后续请求的类中,都是使用一个ServicesCollection。WebHostBuilder类中注册的服务,以及后续用户在Startup类的ConfigureServices方法中注入的服务都是在这个集成在这个ServicesCollection中。
根ServiceProvider: WebHost类中的属性Services返回的ServiceProvider
代码语言:javascript复制private IServiceProvider _applicationServices;
public IServiceProvider Services
{
get
{
return _applicationServices;
}
}
它的实例化是通过IServicesCollection接口的拓展方法BuilderServiceProvider()实例化出来的。此时的实例化也是基于该ServicesCollection中注册的服务。它的生命周期是应用程序从创建到结束的期间。也就是整个aspnet core整个管道的生命周期。asp.net core的DI框架中服务的注册和服务实例化就是从这里开始的,贯彻到整个管道中....
每次请求所使用的ServiceProvider:
该ServiceProvider的生命周期在asp.net core中的定义是scope,即服务范围——其实就是每一次的web请求。这也是aspnet core的DI框架三大生命周期中“Scope”含义:指的是针对每个HTTP请求的上下文,也就是服务范围的生命周期与每个请求上下文绑定在一起。管道总是会创建一个新的ServiceProvider来提供处理每个请求所需的服务,并且这个ServiceProvider将在每次请求处理完成之后被自动回收掉。这样一个ServiceProvider被创建之后直接保存到当前的HTTP上下文中,我们可以利用HttpContext如下所示的RequestServices属性得到这个ServiceProvider。
根ServiceProvider的创建是在WebHostBuilder以及WebHost中,也就是aspnet core管道的创建初始时。终于aspnet core管道结束时。
非根ServiceProvider的创建是在一个中间件中,随后写入HttpContext中,也就是请求上下文。RequestServiceFeature类负责创建非根ServiceProvider:
代码语言:javascript复制private readonly IServiceScopeFactory _scopeFactory;
// 或者 private readonly IServiceProvider _serviceProvider;
_scope = _scopeFactory.CreateScope();
// _scope = _serviceProvider.CreateScope();
_requestServices = _scope.ServiceProvider;
是不是很眼熟?也就是我们平常创建一个新的scope的ServiceProvider的方式。对于IServiceScopeFactory接口,我之前描述过,请看《asp.net core 依赖注入实现全过程粗略剖析(3)》。如此就知道CreateScope方法的设计了。它就是为了创建一个特定范围的ServiceProvider——初始的设计原则应该是为了在每个请求中实现一个特定的ServiceProvider。
如何创建一个ServiceProvider:
1、调用IServicesCollection接口的BuilderServiceProvider方法,该方法创建的是一个根ServiceProvider。
2、调用IServiceProvider接口的CreateScope随后调用ServiceProvider属性。该方法创建的是一个特定范围的ServiceProvider。
总结一下aspnet core获取注册服务的实例如下:
IServiceProvider.CreateScope()
IServiceProvider.GetRequestService<IServiceScopeFactory>
HttpContext.RequestServices.GetService<>
IApplicationBuilder.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
.
CreateScope())
IWebHost.Services.GetService(typeof(IServiceScopeFactory))
疑惑:
这个疑惑我并没有去写代码实践,只是看了一篇博客自己思考了下。原博客<ASP.NET Core 新建线程中使用依赖注入的问题>.即使新开了线程,应该也是共用根ServiceProvider,根ServiceProvider应该不会在新线程中被销毁了。
参考:
ASP.NET Core中如影随形的”依赖注入”[上]: 从两个不同的ServiceProvider说起
蒋金楠老师的博客,每次读都有不同的收获,如果你想要探索底层的原理,那么蒋老师的博客值得深看,多看