深入理解net core中的依賴注入、Singleton、Scoped、Transient(二)


 

 

在上一節的學習中,我們已經知道了通過 IServiceCollection 拓展方法創建 IServiceProvider 默認的是一個類型為 ServiceProvider 對象,並且實際提供創建對象功能的是它的內部為類型為 IServiceProviderEngine 對象,實際上關於 IServiceProvider 的架構比我們想象的還要復雜的多,一個是根容器的概念,另一個就是使用編譯時引擎(CompliedServiceProviderEngine)動態構建表達式樹,提高了創建實例的效率。

容器、引擎和根容器

在這張類圖中,有三個核心接口,IServiceProvider 表示容器,具備提供對象功能,IServiceScope 代表一個具有范圍的節點容器,而 IServiceProviderEngine 是提供對象核心接口,具有一個根容器,每次創建對象的時候都會帶上具有范圍的節點容器。關於容器和引擎這兩個概念如何判斷呢?凡是實現了 IServiceProvider 的都可以稱為容器,同樣的,凡是實現了 IServiceProviderEngine 的都可以稱為引擎,引擎仍然是一個容器,實際上,上圖中所有的類型都是一個容器,因為他們都直接或者間接實現了 IServiceProvider 接口,然而最終負責創建服務實例的必然是一個引擎!

復制代碼
public interface IServiceProvider { object GetService(Type serviceType); } public interface IServiceScope : IDisposable { IServiceProvider ServiceProvider { get; } } internal interface IServiceProviderEngine : IDisposable, IServiceProvider { IServiceScope RootScope { get; } }
復制代碼

ServiceProviderEngineScope

IServiceScope 的默認實現是 ServiceProviderEngineScope,ResolvedServices 存儲已經實例化過的生命周期為 Scoped 的對象,_disposables 存儲通過該根創建的所有實例類型(如果該類型實現了 IDisposable 接口),在調用 Dispose 方法時會釋放 _disposables 中的對象,同時清空 ResolvedServices 中的實例。

復制代碼
internal class ServiceProviderEngineScope : IServiceScope, IServiceProvider { private List<IDisposable> _disposables = new List<IDisposable>(); public ServiceProviderEngineScope(ServiceProviderEngine engine) { Engine = engine; } internal Dictionary<object, object> ResolvedServices { get; } = new Dictionary<object, object>(); public ServiceProviderEngine Engine { get; } public object GetService(Type serviceType) { return Engine.GetService(serviceType, this); } public IServiceProvider ServiceProvider => this; //省略了一些代碼 }
復制代碼

ServiceProviderEngineScope 總在引擎被創建的時候初始化,並且在 GetService 方法中,傳遞的根容器正是這個 Root,所以根容器一般情況不會更改,然而我們可以 CreateScope 方法(來自 IServiceScopeFactory 接口)來創建一個新的根容器(實際上是一個新的節點),實際上到這里可能還是很難理解這個作用域是如何形成的,沒關系,后面還會介紹!

復制代碼
internal abstract class ServiceProviderEngine : IServiceProviderEngine, IServiceScopeFactory { protected ServiceProviderEngine(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback) { Root = new ServiceProviderEngineScope(this); }    public object GetService(Type serviceType) => GetService(serviceType, Root); public ServiceProviderEngineScope Root { get; } public IServiceScope CreateScope() { return new ServiceProviderEngineScope(this); } }
復制代碼

默認的容器 ServiceProvider

ServiceProviderOptions

復制代碼
public static class ServiceCollectionContainerBuilderExtensions { public static ServiceProvider BuildServiceProvider(this IServiceCollection services) { return BuildServiceProvider(services, ServiceProviderOptions.Default); } public static ServiceProvider BuildServiceProvider(this IServiceCollection services, ServiceProviderOptions options) { return new ServiceProvider(services, options); } } public class ServiceProviderOptions { internal static readonly ServiceProviderOptions Default = new ServiceProviderOptions(); public bool ValidateScopes { get; set; } internal ServiceProviderMode Mode { get; set; } = ServiceProviderMode.Dynamic; }
復制代碼

我們知道在 IServiceCollection 的拓展方法 BuildServiceProvider 最終返回的是一個 ServiceProvider,由於默認的 ServiceProviderMode 是 Dynamic,所以默認情況下,提供服務的是一個 DynamicServiceProviderEngine 對象,然而它與 CompiledServiceProviderEngine 唯一的區別就是抽象方法 RealizeService 的實現,前者提供真正的創建對象的方法,而后者將前者提供的創建對象的方法翻譯成表達式樹。

ServiceProvider

復制代碼
public sealed class ServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback { private readonly IServiceProviderEngine _engine; private readonly CallSiteValidator _callSiteValidator; internal ServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options) { IServiceProviderEngineCallback callback = null; if (options.ValidateScopes) { callback = this; _callSiteValidator = new CallSiteValidator(); } switch (options.Mode) { case ServiceProviderMode.Dynamic: _engine = new DynamicServiceProviderEngine(serviceDescriptors, callback); break; case ServiceProviderMode.Runtime: _engine = new RuntimeServiceProviderEngine(serviceDescriptors, callback); break; case ServiceProviderMode.Compiled: _engine = new CompiledServiceProviderEngine(serviceDescriptors, callback); break; default: throw new ArgumentOutOfRangeException(nameof(options.Mode)); } } }
復制代碼

因為 ServiceProviderOptions.Default 提供的參數中 ValidateScoped 默認值是 False,所以這里不打算介紹 IServiceProviderEngineCallback 以及 CallSiteValidator 這兩個類型(和服務實例對象的創建有關,后續介紹)。根據參數 option 的 Mode 為 Dynamic,創建了一個類型為 DynamicServiceProviderEngine 的引擎,實際上該引擎是如何創建對象是后續要講的,這里我們只關注它的創建過程,所以我們又來到了 ServiceProviderEngine 的構造函數。

ServiceProviderEngine 

復制代碼
internal abstract class ServiceProviderEngine : IServiceProviderEngine, IServiceScopeFactory { protected abstract Func<ServiceProviderEngineScope, object> RealizeService(IServiceCallSite callSite); internal ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>> RealizedServices { get; } = new ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>>(); private readonly Func<Type, Func<ServiceProviderEngineScope, object>> _createServiceAccessor; protected ServiceProviderEngine(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback) { _createServiceAccessor = CreateServiceAccessor; _callback = callback; Root = new ServiceProviderEngineScope(this); RuntimeResolver = new CallSiteRuntimeResolver(); ExpressionBuilder = new CallSiteExpressionBuilder(RuntimeResolver, this, Root); CallSiteFactory = new CallSiteFactory(serviceDescriptors); CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite()); CallSiteFactory.Add(typeof(IServiceScopeFactory), new ServiceScopeFactoryCallSite()); } private readonly IServiceProviderEngineCallback _callback; internal CallSiteFactory CallSiteFactory { get; } protected CallSiteRuntimeResolver RuntimeResolver { get; } protected CallSiteExpressionBuilder ExpressionBuilder { get; } public ServiceProviderEngineScope Root { get; } public IServiceScope RootScope => Root; private Func<ServiceProviderEngineScope, object> CreateServiceAccessor(Type serviceType) { var callSite = CallSiteFactory.CreateCallSite(serviceType, new CallSiteChain()); if (callSite != null) { _callback?.OnCreate(callSite); return RealizeService(callSite); } return _ => null; }
復制代碼

這是一個抽象類,還記得我們前面提起過得 IServiceCallSite 嗎?它是創建服務實例的依據,雖然還沒有得到證實,但是我們要堅信!然后我們看抽象方法 RealizeService,它是一個方法,提供一個委托,該委托接受一個根容器,然后返回一個實例對象,可能有點繞,簡而言之這個抽象方法提供一個方法,該方法可以實現服務實例的創建!

復制代碼
internal class DynamicServiceProviderEngine : CompiledServiceProviderEngine { public DynamicServiceProviderEngine(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback) : base(serviceDescriptors, callback) { } protected override Func<ServiceProviderEngineScope, object> RealizeService(IServiceCallSite callSite) { var callCount = 0; return scope => { if (Interlocked.Increment(ref callCount) == 2) { Task.Run(() => base.RealizeService(callSite)); } return RuntimeResolver.Resolve(callSite, scope); }; } }
復制代碼

如果我們對該抽象方法返回的委托理解了,那也會很容易理解字典 RealizedServices,和那個委托一樣,這個字典存儲的是每個服務類型的創建實例的方法,同樣的,委托 _createServiceAccessor 也很好理解。關於 CallSiteRuntimeResolver,這里只需要知道在 DynamicServiceProviderEngine 實現的 RealizeService 方法中,最后返回的委托是根據它來解析 IServiceCallSite 來創建實例的!CallSiteExpressionBuilder 這個類型是在 CompiledServiceProviderEngine中實現將創建實例的過程構建成表達式樹的,詳細過程后續講,但是這里需要知道對於同一個服務,創建其實例的過程應當總是一致的,而這個過程就保存在 RealizedServices 中,而實際創建實例的過程在 DynamicServiceProviderEngine 中,我們在 DynamicServiceProviderEngine 的 RealizeService 方法中發現,如果是第二次創建該實例,則會調用父類 CompiledServiceProviderEngine 的 RealizeService 方法,並且它是以異步方式執行的,盡管如此,最后創建實例的方法仍然是 DynamicServiceProviderEngine 提供的委托,然而 CompiledServiceProviderEngine 的 RealizeService 方法做了些什么呢?

復制代碼
internal class CompiledServiceProviderEngine : ServiceProviderEngine { public CompiledServiceProviderEngine(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback) : base(serviceDescriptors, callback) { } protected override Func<ServiceProviderEngineScope, object> RealizeService(IServiceCallSite callSite) { var realizedService = ExpressionBuilder.Build(callSite); RealizedServices[callSite.ServiceType] = realizedService; return realizedService; } }
復制代碼

實際上這里返回的 realizedService 永遠都不會得到調用(由於它返回的是一個委托,這里的不會調用不是指委托不會調用,這里的永遠不會調用是指不會簡單的通過調用該方法獲取它的返回值),但是這個委托卻永遠的替換了 RealizedServices 中的某個委托(采用了表達式樹重新構建了創建實例的委托),而新的以表達式樹構建的委托是如何地調調用的呢?

復制代碼
internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) { var realizedService = RealizedServices.GetOrAdd(serviceType, _createServiceAccessor); _callback?.OnResolve(serviceType, serviceProviderEngineScope); return realizedService.Invoke(serviceProviderEngineScope); }
復制代碼

 我們看到在 ServiceProviderEngine 的 GetService 方法中,只要 RealizedServices 中已經存在該服務的創建實例的委托就不會通過 CreateServiceAccessor 再去調用抽象方法獲取委托,也就是說被 CompiledServiceProviderEngine 執行它自己的 RealizeService 方法后,以后創建該服務的實例對象總是通過表達式樹創建的。

小結

在這一節中,我們學習了容器創建過程中的一些核心類型,然而最核心的依然在 ServiceProviderEngine 這個抽象類中,盡管提供了抽象方法 RealizeService 允許子類提供創建實例的委托,但是創建實例的具體邏輯依然有它自己的 CallSiteRuntimeResolver 提供,再加上創建實例的方法始終都是通過委托提供的,所以使得 DynamicServiceProviderEngine 和 CompileServiceProviderEngine 這兩個類非常的簡潔,但是依然對 DynamicServiceProviderEngine 是如何使用 CallSiteRuntimeResolver 創建實例的,CompileServiceProviderEngine 又是如何構建表達式樹的,作用域又是如何形成的,因為這些都和 IServiceCallSite 有離不開的關系。


免責聲明!

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



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