Core官方DI解析(5)-ServiceProviderEngine
最后来看看前面一直说的Engine(工作引擎),工作引擎接口是IServiceProviderEngine在ServiceProvider的构造函数中看到了根据指定的Mode创建了不同的实现类,下面先来看一下IServiceProviderEngine接口和其实现类的整体结构
IServiceProviderEngine类型继承关系
internal interface IServiceProviderEngine : IDisposable, IServiceProvider
{
IServiceScope RootScope { get; }
}
`IServiceProvderEngine这个接口`继承了`IServiceProvider`接口,也就是说工作引擎也具有**GetService()**方法,在此接口中具有一个`IServiceScope`类型的**RootScope**,而这个属性则代表是**根容器**
`IServiceScope`代表一个容器接口,这个接口中具有一个`IServiceProvider`类型的属性,返回真正表示容器的一个`IServiceProvider`类型
public interface IServiceScope : IDisposable
{
/// <summary>
/// The <see cref="System.IServiceProvider"/> used to resolve dependencies from the scope.
/// </summary>
IServiceProvider ServiceProvider { get; }
}
IServiceProviderEngine整体结构
IServiceProviderEngine
- ServiceProviderEngine
- CompiledServiceProviderEngine
- DynamicServiceProviderEngine
- RuntimeServiceProviderEngine
- ILEmitServiceProviderEngine
- ExpressionsServiceProviderEngine
上面是目前整个引擎结构,但是前面说过目前只用到了`DynamicServiceProviderEngine`,但是我们看整个类型会看到其实在这几个派生类型中只有一个实现方法`RealizeService(ServiceCallSite callSite)`,而整体结构都是在基类`ServiceProviderEngine`类型中,下面来看看这个基类类型
ServiceProviderEngine
`ServiceProviderEngine`类型是整个结构的核心类型,但是这个类也是一个很简单的类,这个类只是调用`CallSiteFactory`和`CallSiteRuntimeResolver`,由下图可以看到这个类型是一个抽象类,并且实现了`IServiceProviderEngine`和`IServiceScopeFactory`接口接口
`IServiceScopeFactory`这个接口提供了一个创建子容器方法我们已知道`IServiceProviderEngine`接口*继承*了`IServiceProvider`接口,那么也就是说在`ServiceProviderEngine`已经具备以下两个功能
1.获取服务实例对象
2.创建子容器
internal abstract class ServiceProviderEngine : IServiceProviderEngine, IServiceScopeFactory{}
// 创建子容器接口
public interface IServiceScopeFactory
{
//
IServiceScope CreateScope();
}
下面首先来看一下此类中拥有的字段+属性,这些属性都是在构造器中进行了实例化
_callback:
这个字段就是顶级容器时检查scoped生命周期的访问者对象,这个从
ServiceProvider类中时进行传入的,在这里并不细讲这个类型RealizedServices:
这个属性是缓存根据容器获取服务实例对象委托,其中Key为ServiceType
_createServiceAccessor:
这是一个根据类型获取一个根据容器获取服务实例对象的委托,可以看到使用了一个CreateServiceAccessor()进行赋值,CreateServiceAccessor()是此类型的一个核心方法,下面介绍
CallSiteFactory:
ServiceCallSite工厂类型,在构造器中实例化,可以看到实例化时将serviceDescriptors进行传入,并且可以看到在构造器中向此实例对象中添加了一个IServiceProvider和IServiceScopeFactoryRuntimeResolver:
这个属性是是获取服务实例的访问者对象,可以看到在构造器中进行传入
Root:
Root代表是一个顶级容器
ServiceProviderEngineScope类型则是一个具体的容器类型,这个类型中缓存了所有的具体服务实例对象,这个类型实现了IServiceScope接口,从下面代码可以看到RootScope其实就是直接返回了Root属性RootScope:
这也是一个根容器实例对象,直接返回的Root属性
// 顶级容器时scoped生命周期实例检查策略
private readonly IServiceProviderEngineCallback _callback;
// 根据类型创建构建服务的委托
private readonly Func<Type, Func<ServiceProviderEngineScope, object>> _createServiceAccessor;
// 此实例是否被销毁
private bool _disposed;
// 缓存根据容器获取服务实例的委托, Key为注册类型
internal ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>> RealizedServices { get; }
// CallSite工厂类属性,此类型用于根据指定实例化方式来创建对应的CallSite
internal CallSiteFactory CallSiteFactory { get; }
// 访问者对象,此对象对进行实例和缓存具体真正的对象
protected CallSiteRuntimeResolver RuntimeResolver { get; }
// 根容器实例属性
public ServiceProviderEngineScope Root { get; }
// 根容器实例属性
public IServiceScope RootScope => Root;
// 构造器
protected ServiceProviderEngine(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback)
{
_createServiceAccessor = CreateServiceAccessor;
_callback = callback;
// 实例化根容器
Root = new ServiceProviderEngineScope(this);
// 实例化 CallSite对象访问者对象
RuntimeResolver = new CallSiteRuntimeResolver();
// 实例化CallSiteFactory类型对象
CallSiteFactory = new CallSiteFactory(serviceDescriptors);
CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite());
// 缓存一个ServiceScopeFactoryCallSite服务,相当于缓存一个ServiceProviderEngine,根据此对象进行创建子容器
CallSiteFactory.Add(typeof(IServiceScopeFactory), new ServiceScopeFactoryCallSite());
// 缓存实例化对象的工厂
RealizedServices = new ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>>();
}
`ServiceProviderEngine`类型中方法只有**GetService()**,**CreateScope()**,**CreateServiceAccessor()**,**Dispose()**和一个抽象方法**RealizeService()**,其中几个派生类中都只是实现了**RealizeService()**,这个一会再看,下面来看看`ServiceProviderEngine`类中的这几个方法
RealizeService:
这个方法由派生类继承,由指定的
ServiceCallSite缓存并获取 服务实例的委托GetService:
这个方法获取服务实例对象,可以看到具有两个此方法,并且第一个调用了第二个,并将顶级容器Root进行了传入,而在第二个方法中,获取并添加_createServiceAccessor委托,然后调用此委托进行获取服务实例
CreateScope:
这个方法是创建一个子容器对象,在这个方法中可以看到直接 new 了一个容器对象,并将当前对象进行了传入。从此可以得知为什么所有容器共享顶级容器的服务注册了
Dispose:
清除当前对象,并清除顶级容器
CreateServiceAccessor:
这个方法可以看到根据ServiceType进行获取指定
ServiceCallSite,然后再调用派生类实现的RealizeService()进行返回
// 抽象类型,子类实现
protected abstract Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite);
public object GetService(Type serviceType) => GetService(serviceType, Root);
internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
{
if (_disposed)
ThrowHelper.ThrowObjectDisposedException();
// 添加并获取根据容器对象实例化对象的方法,其方法由子类进行重写
var realizedService = RealizedServices.GetOrAdd(serviceType, _createServiceAccessor);
// 验证是否允许进行实例化对象
_callback?.OnResolve(serviceType, serviceProviderEngineScope);
return realizedService.Invoke(serviceProviderEngineScope);
}
public void Dispose()
{
_disposed = true;
Root.Dispose();
}
// 实例化的子容器
public IServiceScope CreateScope()
{
if (_disposed)
ThrowHelper.ThrowObjectDisposedException();
return new ServiceProviderEngineScope(this);
}
private Func<ServiceProviderEngineScope, object> CreateServiceAccessor(Type serviceType)
{
// 根据基类类型获取对应的CallSite
var callSite = CallSiteFactory.GetCallSite(serviceType, new CallSiteChain());
if (callSite != null)
{
// 缓存当前注册
_callback?.OnCreate(callSite);
return RealizeService(callSite);
}
return _ => null;
}
DynamicServiceProviderEngine和CompiledServiceProviderEngine
下面来看一下`DynamicServiceProviderEngine`和`CompiledServiceProviderEngine`这两个派生类型,从上面继承关系可以看到这两个派生类型是一个继承关系 `DynamicServiceProviderEngine`继承于`CompiledServiceProviderEngine`.
internal class DynamicServiceProviderEngine : CompiledServiceProviderEngine{}
在这两个派生类型中都只是实现了基类的RealizeService(),下面先来看看CompiledServiceProviderEngine类的实现
可以看到CompiledServiceProviderEngine类中具有一个ExpressionResolverBuilder对象,这个类是使用表达式树生成结构,这个实例在构造函数进行创建,并且将CallSiteRuntimeResolver对象,本对象和顶级容器进行了传入,可以看到在重写的方法中是调用了ExpressionResolverBuilder对象的Build(),这个方法会生成一个Func<ServiceProviderEngineScope,Object>委托,然后缓存此委托,
注:
ExpressionResolverBuilder这个类挺复杂,我也没看懂,所以在此不介绍,有兴趣的可以直接看源码
internal abstract class CompiledServiceProviderEngine : ServiceProviderEngine
{
// 表达式树生成对象
public ExpressionResolverBuilder ExpressionResolverBuilder { get; }
// 构造函数
public CompiledServiceProviderEngine(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback) : base(serviceDescriptors, callback)
=> ExpressionResolverBuilder = new ExpressionResolverBuilder(RuntimeResolver, this, Root);
// 重写RealizeService方法
protected override Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite)
{
// 使用表达式树进行创建一个Func<ServiceProviderEngineScope,Object>委托
var realizedService = ExpressionResolverBuilder.Build(callSite);
// 直接将表达式生成的委托进行替换之前的缓存
RealizedServices[callSite.ServiceType] = realizedService;
return realizedService;
}
}
而在`RuntimeServiceProviderEngine`类中,则只是实现了**RealizeService()**,从下面代码可以看出在第一次调用时是直接调用`CallSiteRuntimeResolver`这个访问者获取的实例数据,而在第二次才调用的基类,也就是`CompiledServiceProviderEngine`进行了缓存,但是至于为什么这样干,我没有弄清。。。
internal class DynamicServiceProviderEngine : CompiledServiceProviderEngine
{
public DynamicServiceProviderEngine(
IEnumerable<ServiceDescriptor> serviceDescriptors,
IServiceProviderEngineCallback callback)
: base(serviceDescriptors, callback)
{
}
protected override Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite)
{
var callCount = 0;
return scope =>
{
if (Interlocked.Increment(ref callCount) == 2)
{
// 如果当前是第二次调用,则调用父级进行缓存
Task.Run(() => base.RealizeService(callSite));
}
// 调用访问者进行根据当前容器和CallSite进行实例化服务对象
return RuntimeResolver.Resolve(callSite, scope);
};
}
}
Core官方DI解析(5)-ServiceProviderEngine的更多相关文章
- Core官方DI解析(3)-ServiceCallSite.md
上一篇说过在整个DI框架中IServiceProviderEngine是核心,但是如果直接看IServiceProviderEngine派生类其实看不出也没什么东西,因为这个类型其实都是调用的其它对象 ...
- Core官方DI解析(4)--CallSiteRuntimeResolver
CallSiteRuntimeResolver类型是一个创建或获取服务实例的类型,这个类型继承了CallSiteVisitor<TArgument, TResult>这个类型,也是使用 ...
- Core官方DI解析(2)-ServiceProvider
ServiceProvider ServiceProvider是我们用来获取服务实例对象的类型,它也是一个特别简单的类型,因为这个类型本身并没有做什么,其实以一种代理模式,其核心功能全部都在IServ ...
- Core官方DI剖析(1)--ServiceProvider类和ServiceCollection类
前段时间看了蒋老师的Core文章,对于DI那一块感觉挺有意思,然后就看了一下Core官方DI的源码,这也算是第一个看得懂大部分源码的框架,虽然官方DI相对来说特别简单, 官方DI相对于其它框架(例如 ...
- abp vnext2.0核心组件之.Net Core默认DI组件切换到AutoFac源码解析
老版Abp对Castle的严重依赖在vnext中已经得到了解决,vnext中DI容器可以任意更换,为了实现这个功能,底层架构相较于老版abp,可以说是进行了高度重构.当然这得益于.Net Core的D ...
- Asp.Net Core中DI的知识总结
在asp.net core中DI的概念是由这几部分组成的: IServiceCollection,保存IServiceDescriptor实例的列表 IServiceProvider,只有一个方法Ge ...
- asp.net core的DI框架思考以及服务实例的获取方式总结
转载请注明出处: https://home.cnblogs.com/u/zhiyong-ITNote/ 整个asp.net core管道从WebHostBuilder到WebHost到后续请求的类中, ...
- 实战Asp.Net Core:DI生命周期
title: 实战Asp.Net Core:DI生命周期 date: 2018-11-30 21:54:52 --- 1.前言 Asp.Net Core 默认支持 DI(依赖注入) 软件设计模式,那使 ...
- 阅读DMA Controller Core 官方手册
阅读DMA Controller Core 官方手册 DMA控制器框架图 怎样去设定一个DMA控制器 实例化DMA控制器 参数配置界面如下图所示: 对于width of the DMA length ...
随机推荐
- .NET Core 2.1来了!
太棒了! .NET Core 2.0正式发布至今已经过去了大半年,这大半年说长不长说短不短,这段时间里,我是充分地体会到了微软的诚意,那就是认认真真打造一个优秀的开源平台.这大半年的时间里,微软一直在 ...
- SUSE12SP3-Mycat(3)Server.xml配置详解
简介 server.xml 几乎保存了所有 mycat 需要的系统配置信息.其在代码内直接的映射类为 SystemConfig 类. user 标签 <user name="test& ...
- Vue(day7)
一.环境搭建 下面我们需要为后面要做的Vue项目搭建开发环境. 1.基本的运行环境 该项目使用node& vue在webpack环境下进行开发.首先安装基本的模块文件: npm install ...
- ASP.NET Core中使用GraphQL - 第六章 使用EF Core作为持久化仓储
ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 ASP ...
- 《前端之路》之 初识 JavaScript
01 初识 JavaScript 作为在码农圈混迹了 四五年的老码畜来说,学习一门新的语言,就仿佛是老司机开新车一样 轻车熟路. 为什么会这么快呢? 因为各种套路啊- 任何一种计算机语言的最开始都是和 ...
- 利用Bootstrap Paginator插件和KnockoutJS完成分页功能
在最近一个项目中,需要结合一堆条件查询并对查询的结果数据完成一个简单分页功能,可是做着做着,自己的思路越来越模糊,做到心态崩溃!!! 哈哈,特此花点时间重新总结,并从最简单的分页,然后向多条件查询分页 ...
- java~springboot~gradle里的docker集成
在springboot里,我们的task任务可以添加docker构建的功能,在gradle集成环境里,直接可以实现编译,测试,打包镜像的流水线作业,很是方便! 下面分享给大家,在gradle里添加do ...
- 什么是Servlet(原理,从访问到方法)
Servlet简介 Servlet是SUN公司提供的一门用于开发动态WEB资源的技术.SUN公司在其API中提供了一个Servlet接口,用户若想开发一个动态WEB资源(即开发一个Java程序向浏览器 ...
- merge和rebase的区别
前言 我从用git就一直用rebase,但是新的公司需要用merge命令,我不是很明白,所以查了一些资料,总结了下面的内容,如果有什么不妥的地方,还望指正,我一定虚心学习. merge和rebase ...
- swagger文档转换为WebApiClient声明式代码
1 swagger简介 Swagger是一个规范且完整的框架,提供描述.生产.消费和可视化RESTful Web Service.其核心是使用json来规范描述RESTful接口,另外有提供UI来查看 ...