Core官方DI解析(5)-ServiceProviderEngine

时间:2023-12-11 17:50:02

最后来看看前面一直说的Engine(工作引擎),工作引擎接口是IServiceProviderEngineServiceProvider的构造函数中看到了根据指定的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进行传入,并且可以看到在构造器中向此实例对象中添加了一个IServiceProviderIServiceScopeFactory

  • RuntimeResolver:

    这个属性是是获取服务实例的访问者对象,可以看到在构造器中进行传入

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