Core官方DI解析(2)-ServiceProvider


ServiceProvider

ServiceProvider是我們用來獲取服務實例對象的類型,它也是一個特別簡單的類型,因為這個類型本身並沒有做什么,其實以一種代理模式,其核心功能全部都在IServiceProviderEngine實現類中

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

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

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

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

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

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

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

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

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM