Core官方DI解析(5)-ServiceProviderEngine

莫問今朝·發表於2018-11-30

最後來看看前面一直說的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);
          };
     }
}

相關文章