Core官方DI解析(2)-ServiceProvider
ServiceProvider
ServiceProvider是我們用來獲取服務(wù)實(shí)例對象的類型,它也是一個特別簡單的類型,因?yàn)檫@個類型本身并沒有做什么,其實(shí)以一種代理模式,其核心功能全部都在IServiceProviderEngine實(shí)現(xiàn)類中
ServiceProvider還具有一個擴(kuò)展類型ServiceProviderServiceExtensions,在擴(kuò)展類型之中實(shí)現(xiàn)了一些我們經(jīng)常使用的獲取服務(wù)實(shí)例方法,比如GetServices()和GetRequiredService()方法,還實(shí)現(xiàn)了獲取子容器方法CreateScope(),下面來具體的看一下這個類型
從下面代碼看到ServiceProvider一個實(shí)現(xiàn)了三個接口
- IServiceProvider 獲取服務(wù)接口,這個接口是位于System程序集下的,而這個接口只有一個object GetService(Type serviceType)方法,也就是說我們常用很多方法包括泛型獲取都是來自于擴(kuò)展類中
- IDisposable 說明此對象需要被釋放
- IServiceProviderEngineCallback 這個接口就是檢驗(yàn)validateScopes時使用的,接口具有兩個方法OnCreate()和OnResolve()分別用于創(chuàng)建服務(wù)實(shí)例時緩存和校驗(yàn),?
? ServiceProvider這個類型其實(shí)挺簡單,從下面代碼中GetService()方法可以看出它只是代理了一個IServiceProviderEngine實(shí)現(xiàn)類型,
**_engine**: 作為一個IServiceProviderEngine接口,這個接口是ServiceProvider的工作引擎接口,也是一個核心類型,下一章再詳細(xì)講解這個接口及其實(shí)現(xiàn)類型
**_callSiteValidator: 這是一個驗(yàn)證ValidateScopes的緩存類型(訪問者模式),可以看到,在構(gòu)造函數(shù)中只有當(dāng)ValidateScopes為true時才實(shí)例化此對象,然后在獲取服務(wù)實(shí)例時通過OnCreate()進(jìn)行緩存和通過OnResolve()**進(jìn)行校驗(yàn)
? ServiceProvider的實(shí)例化方式在上一章已經(jīng)說過,利用ServiceDescriptor集合和ServiceProviderOptions進(jìn)行實(shí)例化,可以看到,在構(gòu)造方法中首先通過ValidateScopes屬性來進(jìn)行實(shí)例化CallSiteValidator和將當(dāng)前對象賦值給IServiceProviderEngineCallback類型變量
將this賦值給IServiceProviderEngineCallback是為了讓IServiceProviderEngine進(jìn)行調(diào)用驗(yàn)證
? 然后通過ServiceProviderMode這個枚舉進(jìn)行判斷實(shí)例化的具體引擎對象,四個枚舉對應(yīng)四種引擎對象,前面已經(jīng)說過目前DI只使用了Dynamic這一種,下面說IServiceProviderEngineCallback時也只說這一種
public sealed class ServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback {// ServiceProvider工作引擎接口 // 這個接口是一個核心接口 // 使用這個接口的子類進(jìn)行調(diào)用緩存各種注冊服務(wù)和調(diào)用訪問者對象進(jìn)行獲取實(shí)例對象private readonly IServiceProviderEngine _engine;/// 此屬性緩存當(dāng)前注冊類型,當(dāng)ServiceProviderOptions.ValidateScopes為true進(jìn)行驗(yàn)證private readonly CallSiteValidator _callSiteValidator;internal ServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options){IServiceProviderEngineCallback callback = null;if (options.ValidateScopes){callback = this;_callSiteValidator = new CallSiteValidator();}// 根據(jù)ServiceProviderMode進(jìn)行實(shí)例化對應(yīng)的工作引擎類型switch (options.Mode){case ServiceProviderMode.Dynamic:// 實(shí)例化 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));}}/// 獲取指定類型的服務(wù)對象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的擴(kuò)展類型,提供了更佳便捷,下面就來看看這個這個擴(kuò)展類提供的方法
?
? 在這個擴(kuò)展類中就擴(kuò)展了GetRequiredService(),GetServices()和CreateScope()三個方法,前兩個也是獲取服務(wù)實(shí)例,第三個獲取一個子IServiceProvider,也就是說獲取一個子容器
?
? GetRequiredService()方法是如果獲取的當(dāng)前類型并沒有被注冊,那么就會拋出InvalidOperationException異常,從下面代碼可以看出,GetRequiredService()方法首先判斷當(dāng)前ServicePrivider是否是ISupportRequiredService的實(shí)現(xiàn)類,如果是,則就返回自身的GetRequiredService()方法,如果不是,就直接調(diào)用GetService(),如果返回服務(wù)實(shí)例為NULL,就拋出異常.
ISupportRequiredService接口中只定義了GetRequiredService(),然而現(xiàn)在的ServiceProvider類型并沒有實(shí)現(xiàn)ISupportRequiredService接口
? GetServices()方法是獲取當(dāng)前類型的所有服務(wù)實(shí)例,可以看到這個方法無非是調(diào)用的GetRequiredService(),只不過參數(shù)是一個IEnumerable集合,在內(nèi)部使用IEnumerable參數(shù)獲取服務(wù)實(shí)例是一個特殊處理,這個在后面就可以看到
?
? CreateScope()方法是一個獲取子類容器的,獲取方式從下面代碼看的也是通過服務(wù)注冊的方式獲取服務(wù)實(shí)例,也就是說內(nèi)部進(jìn)行了注冊,這個注冊是在ServiceProviderEngine類中
public static class ServiceProviderServiceExtensions {// 泛型重載 public static T GetService<T>(this IServiceProvider provider)=> (T)provider.GetService(typeof(T));// 如果當(dāng)前服務(wù)并未注冊,則會拋出異常public static object GetRequiredService(this IServiceProvider provider, Type serviceType){// 如果當(dāng)前ServiceProvider實(shí)現(xiàn)了 ISupportRequiredService // 則直接調(diào)用當(dāng)前ServiceProvier的GetRequiredService獲取服務(wù)實(shí)例var requiredServiceSupportingProvider = provider as ISupportRequiredService;if (requiredServiceSupportingProvider != null)return requiredServiceSupportingProvider.GetRequiredService(serviceType);// 如果當(dāng)前ServiceProvider未實(shí)現(xiàn)ISupportRequiredService// 就直接調(diào)用GetService獲取服務(wù)實(shí)例,但是如果服務(wù)實(shí)例為空,則拋出異常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>的所有服務(wù)實(shí)例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類型作為當(dāng)前集合的泛型參數(shù)var genericEnumerable = typeof(IEnumerable<>).MakeGenericType(serviceType);return (IEnumerable<object>)provider.GetRequiredService(genericEnumerable);}// 創(chuàng)建一個子IServiceProvider實(shí)例// 內(nèi)部其實(shí)將IServiceScopeFactory接口和一個ServiceScopeFactoryCallSite進(jìn)行了注冊// 這個是在IServiceProviderEngine的實(shí)現(xiàn)類ServiceProviderEngine中的,以后在詳細(xì)介紹public static IServiceScope CreateScope(this IServiceProvider provider)=> provider.GetRequiredService<IServiceScopeFactory>().CreateScope(); }轉(zhuǎn)載于:https://www.cnblogs.com/yan7/p/10024341.html
總結(jié)
以上是生活随笔為你收集整理的Core官方DI解析(2)-ServiceProvider的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Docker(2):使用Dockerfi
- 下一篇: SNMP学习笔记之SNMPv3的配置和认