Core官方DI解析(2)-ServiceProvider
ServiceProvider
ServiceProvider是我們用來獲取服務實例對象的類型,它也是一個特別簡單的類型,因為這個類型本身并沒有做什么,其實以一種代理模式,其核心功能全部都在IServiceProviderEngine實現(xiàn)類中
ServiceProvider還具有一個擴展類型ServiceProviderServiceExtensions,在擴展類型之中實現(xiàn)了一些我們經常使用的獲取服務實例方法,比如GetServices()和GetRequiredService()方法,還實現(xiàn)了獲取子容器方法CreateScope(),下面來具體的看一下這個類型
從下面代碼看到ServiceProvider一個實現(xiàn)了三個接口
- IServiceProvider 獲取服務接口,這個接口是位于System程序集下的,而這個接口只有一個object GetService(Type serviceType)方法,也就是說我們常用很多方法包括泛型獲取都是來自于擴展類中
- IDisposable 說明此對象需要被釋放
- IServiceProviderEngineCallback 這個接口就是檢驗validateScopes時使用的,接口具有兩個方法OnCreate()和OnResolve()分別用于創(chuàng)建服務實例時緩存和校驗,?
? ServiceProvider這個類型其實挺簡單,從下面代碼中GetService()方法可以看出它只是代理了一個IServiceProviderEngine實現(xiàn)類型,
**_engine**: 作為一個IServiceProviderEngine接口,這個接口是ServiceProvider的工作引擎接口,也是一個核心類型,下一章再詳細講解這個接口及其實現(xiàn)類型
**_callSiteValidator: 這是一個驗證ValidateScopes的緩存類型(訪問者模式),可以看到,在構造函數(shù)中只有當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();}// 根據(jù)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的實現(xiàn)類,如果是,則就返回自身的GetRequiredService()方法,如果不是,就直接調用GetService(),如果返回服務實例為NULL,就拋出異常.
ISupportRequiredService接口中只定義了GetRequiredService(),然而現(xiàn)在的ServiceProvider類型并沒有實現(xiàn)ISupportRequiredService接口
? GetServices()方法是獲取當前類型的所有服務實例,可以看到這個方法無非是調用的GetRequiredService(),只不過參數(shù)是一個IEnumerable集合,在內部使用IEnumerable參數(shù)獲取服務實例是一個特殊處理,這個在后面就可以看到
?
? 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實現(xiàn)了 ISupportRequiredService // 則直接調用當前ServiceProvier的GetRequiredService獲取服務實例var requiredServiceSupportingProvider = provider as ISupportRequiredService;if (requiredServiceSupportingProvider != null)return requiredServiceSupportingProvider.GetRequiredService(serviceType);// 如果當前ServiceProvider未實現(xiàn)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類型作為當前集合的泛型參數(shù)var genericEnumerable = typeof(IEnumerable<>).MakeGenericType(serviceType);return (IEnumerable<object>)provider.GetRequiredService(genericEnumerable);}// 創(chuàng)建一個子IServiceProvider實例// 內部其實將IServiceScopeFactory接口和一個ServiceScopeFactoryCallSite進行了注冊// 這個是在IServiceProviderEngine的實現(xiàn)類ServiceProviderEngine中的,以后在詳細介紹public static IServiceScope CreateScope(this IServiceProvider provider)=> provider.GetRequiredService<IServiceScopeFactory>().CreateScope(); }轉載于:https://www.cnblogs.com/yan7/p/10024341.html
總結
以上是生活随笔為你收集整理的Core官方DI解析(2)-ServiceProvider的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Docker(2):使用Dockerfi
- 下一篇: SNMP学习笔记之SNMPv3的配置和认