Core官方DI解析(2)-ServiceProvider

ServiceProvider

ServiceProvider是咱們用來獲取服務實例對象的類型,它也是一個特別簡單的類型,由於這個類型自己並無作什麼,其實以一種代理模式,其核心功能所有都在IServiceProviderEngine實現類中c#

ServiceProvider還具備一個擴展類型ServiceProviderServiceExtensions,在擴展類型之中實現了一些咱們常常使用的獲取服務實例方法,好比GetServices()GetRequiredService()方法,還實現了獲取子容器方法CreateScope(),下面來具體的看一下這個類型緩存

從下面代碼看到ServiceProvider一個實現了三個接口ide

  • IServiceProvider 獲取服務接口,這個接口是位於System程序集下的,而這個接口只有一個object GetService(Type serviceType)方法,也就是說咱們經常使用不少方法包括泛型獲取都是來自於擴展類中
  • IDisposable 說明此對象須要被釋放
  • IServiceProviderEngineCallback 這個接口就是檢驗validateScopes時使用的,接口具備兩個方法OnCreate()OnResolve()分別用於建立服務實例時緩存和校驗,​
public sealed class ServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback
{}

ServiceProvider這個類型其實挺簡單,從下面代碼中GetService()方法能夠看出它只是代理了一個IServiceProviderEngine實現類型,函數

_engine: 做爲一個IServiceProviderEngine接口,這個接口是ServiceProvider的工做引擎接口,也是一個核心類型,下一章再詳細講解這個接口及其實現類型ui

_callSiteValidator: 這是一個驗證ValidateScopes的緩存類型(訪問者模式),能夠看到,在構造函數中只有當ValidateScopes爲true時才實例化此對象,而後在獲取服務實例時經過OnCreate()進行緩存和經過OnResolve()進行校驗this

ServiceProvider的實例化方式在上一章已經說過,利用ServiceDescriptor集合和ServiceProviderOptions進行實例化,能夠看到,在構造方法中首先經過ValidateScopes屬性來進行實例化CallSiteValidator和將當前對象賦值給IServiceProviderEngineCallback類型變量代理

this賦值給IServiceProviderEngineCallback是爲了讓IServiceProviderEngine進行調用驗證code

​ 而後經過ServiceProviderMode這個枚舉進行判斷實例化的具體引擎對象,四個枚舉對應四種引擎對象,前面已經說過目前DI只使用了Dynamic這一種,下面說IServiceProviderEngineCallback時也只說這一種orm

public sealed class ServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback
{
    //		ServiceProvider工做引擎接口	
    //		這個接口是一個核心接口   
    //		使用這個接口的子類進行調用緩存各類註冊服務和調用訪問者對象進行獲取實例對象
     private readonly IServiceProviderEngine _engine;
     
     ///         此屬性緩存當前註冊類型,當ServiceProviderOptions.ValidateScopes爲true進行驗證
     private readonly CallSiteValidator _callSiteValidator;

     internal ServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options)
     {
          IServiceProviderEngineCallback callback = null;
          if (options.ValidateScopes)
          {
               callback = this;
               _callSiteValidator = new CallSiteValidator();
          }
          //		根據ServiceProviderMode進行實例化對應的工做引擎類型
          switch (options.Mode)
          {
               case ServiceProviderMode.Dynamic:
                    //      實例化 DynamicServiceProviderEngine
                    _engine = new DynamicServiceProviderEngine(serviceDescriptors, callback);
                    break;
               case ServiceProviderMode.Runtime:
                    _engine = new RuntimeServiceProviderEngine(serviceDescriptors, callback);
                    break;
                    case ServiceProviderMode.ILEmit:
                    _engine = new ILEmitServiceProviderEngine(serviceDescriptors, callback);
               break;
                    case ServiceProviderMode.Expressions:
                    _engine = new ExpressionsServiceProviderEngine(serviceDescriptors, callback);
                    break;
               default:
               	throw new NotSupportedException(nameof(options.Mode));
          }
     }

     /// 獲取指定類型的服務對象
     public object GetService(Type serviceType) => _engine.GetService(serviceType);

     public void Dispose() => _engine.Dispose();

	void IServiceProviderEngineCallback.OnCreate(ServiceCallSite callSite)
       =>_callSiteValidator.ValidateCallSite(callSite);

     void IServiceProviderEngineCallback.OnResolve(Type serviceType, IServiceScope scope)
      =>_callSiteValidator.ValidateResolution(serviceType, scope, _engine.RootScope);
}

ServiceProviderServiceExtensions

​ 前面說過這個類是ServiceProvider的擴展類型,提供了更佳便捷,下面就來看看這個這個擴展類提供的方法對象

​ 在這個擴展類中就擴展了GetRequiredService(),GetServices()CreateScope()三個方法,前兩個也是獲取服務實例,第三個獲取一個子IServiceProvider,也就是說獲取一個子容器

GetRequiredService()方法是若是獲取的當前類型並無被註冊,那麼就會拋出InvalidOperationException異常,從下面代碼能夠看出,GetRequiredService()方法首先判斷當前ServicePrivider是不是ISupportRequiredService的實現類,若是是,則就返回自身的GetRequiredService()方法,若是不是,就直接調用GetService(),若是返回服務實例爲NULL,就拋出異常.

ISupportRequiredService接口中只定義了GetRequiredService(),然而如今的ServiceProvider類型並無實現ISupportRequiredService接口

GetServices()方法是獲取當前類型的全部服務實例,能夠看到這個方法無非是調用的GetRequiredService(),只不過參數是一個IEnumerable 集合,在內部使用IEnumerable 參數獲取服務實例是一個特殊處理,這個在後面就能夠看到

CreateScope()方法是一個獲取子類容器的,獲取方式從下面代碼看的也是經過服務註冊的方式獲取服務實例,也就是說內部進行了註冊,這個註冊是在ServiceProviderEngine類中

public static class ServiceProviderServiceExtensions
{
	//		泛型重載    
     public static T GetService<T>(this IServiceProvider provider)
          => (T)provider.GetService(typeof(T));
     
     //		若是當前服務並未註冊,則會拋出異常
     public static object GetRequiredService(this IServiceProvider provider, Type serviceType)
     {
          //      若是當前ServiceProvider實現了 ISupportRequiredService 
          //      則直接調用當前ServiceProvier的GetRequiredService獲取服務實例
          var requiredServiceSupportingProvider = provider as ISupportRequiredService;
          if (requiredServiceSupportingProvider != null)
             return requiredServiceSupportingProvider.GetRequiredService(serviceType);
          //      若是當前ServiceProvider未實現ISupportRequiredService
          //      就直接調用GetService獲取服務實例,可是若是服務實例爲空,則拋出異常
          var service = provider.GetService(serviceType);
          if (service == null)
              throw new InvalidOperationException(Resources.FormatNoServiceRegistered(serviceType));
          return service;
     }
     
	//		泛型版本
     public static T GetRequiredService<T>(this IServiceProvider provider)
          => (T)provider.GetRequiredService(typeof(T));

     //		獲取指定註冊類型<T>的全部服務實例
     public static IEnumerable<T> GetServices<T>(this IServiceProvider provider)
          => provider.GetRequiredService<IEnumerable<T>>();

     //		同上,
     public static IEnumerable<object> GetServices(this IServiceProvider provider, Type serviceType)
     {
          //      製造一個serviceType類型的IEnumberable<>集合,serviceTypele類型做爲當前集合的泛型參數
          var genericEnumerable = typeof(IEnumerable<>).MakeGenericType(serviceType);
          return (IEnumerable<object>)provider.GetRequiredService(genericEnumerable);
     }

     //		建立一個子IServiceProvider實例
     //		內部其實將IServiceScopeFactory接口和一個ServiceScopeFactoryCallSite進行了註冊
     //		這個是在IServiceProviderEngine的實現類ServiceProviderEngine中的,之後在詳細介紹
     public static IServiceScope CreateScope(this IServiceProvider provider)
          => provider.GetRequiredService<IServiceScopeFactory>().CreateScope();
}
相關文章
相關標籤/搜索