国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[Asp.net 5] DependencyInjection項目代碼分析4-微軟的實現(3)

2019-11-17 02:07:07
字體:
來源:轉載
供稿:網友

[asp.net 5] DependencyInjection項目代碼分析4-微軟的實現(3)

這個系列已經寫了5篇,鏈接地址如下:

[Asp.net 5] DependencyInjection項目代碼分析

[Asp.net 5] DependencyInjection項目代碼分析2-Autofac

[Asp.net 5] DependencyInjection項目代碼分析3-Ninject

[Asp.net 5] DependencyInjection項目代碼分析4-微軟的實現(1)

[Asp.net 5] DependencyInjection項目代碼分析4-微軟的實現(2)

如果想對本篇有個更好的了解,建議需要先看

“[Asp.net 5] DependencyInjection項目代碼分析”

“[Asp.net 5] DependencyInjection項目代碼分析4-微軟的實現(1)”

“[Asp.net 5] DependencyInjection項目代碼分析4-微軟的實現(2)”。

在之前的“上“、”中“倆篇已經介紹了ServiceTable、IGenericService、IService、IServiceCallSite、ServiceEntryGenericService、InstanceService、FactoryService、Service等類。本節主要介紹核心的”ServicePRovider“類。

IServiceProvider類

IServiceProvider類是微軟這套DependencyInjection中直接對外的接口。而ServiceProvider是直接實現IServiceProvider并且對外直接提供功能的核心類。

對于ServiceProvider不僅要能夠獲取注入的類,還需要根據不同定義的范圍獲取不同范圍的注入類。對于不同的范圍(Transient、Scoped、Singleton),ServiceProvider需要使用不同的邏輯。我們簡單分析下。

  • 對于Transient,每次都創建一個新的實例,所以代碼中只需直接創建該注入類的實例即可,不需要對該類進行緩存;
  • 對于Singleton,全局只有一個實例,代碼中可以將創建的對象緩存到靜態的字典表中,之后每次需要該類型實例首先到全局靜態字典表中去查找如果存在則直接返回,不存在創建后加入到字典表中,之后返回。(實際上源碼中并未緩存到全局變量中,具體實現方式后面會講解
  • 對于Scoped,每個Scope內是唯一的,不同Scope范圍是不同的。這個就比較難實現。不過我們可以通過外部調用的代碼簡單的猜測下,之后我們通過查看源代碼進行驗證。

下面是不同Scoped范圍的代碼調用。

public void ScopedServiceCanBeResolved()        {            IServiceProvider container = CreateContainer();            var scopeFactory = container.GetService<IServiceScopeFactory>();            using (var scope = scopeFactory.CreateScope())            {                var containerScopedService = container.GetService<IFakeScopedService>();                var scopedService1 = scope.ServiceProvider.GetService<IFakeScopedService>();                var scopedService2 = scope.ServiceProvider.GetService<IFakeScopedService>();                Assert.NotEqual(containerScopedService, scopedService1);                Assert.Equal(scopedService1, scopedService2);            }        }        [Fact]        public void NestedScopedServiceCanBeResolved()        {            IServiceProvider container = CreateContainer();            IServiceScopeFactory outerScopeFactory = container.GetService<IServiceScopeFactory>();            using (var outerScope = outerScopeFactory.CreateScope())            {                var innerScopeFactory = outerScope.ServiceProvider.GetService<IServiceScopeFactory>();                using (var innerScope = innerScopeFactory.CreateScope())                {                    var outerScopedService = outerScope.ServiceProvider.GetService<IFakeScopedService>();                    var innerScopedService = innerScope.ServiceProvider.GetService<IFakeScopedService>();                    Assert.NotEqual(outerScopedService, innerScopedService);                }            }        }
CreateScope

我們可以根據不同Scoped的注入實例,實際上是通過獲取不同的IServiceScope對象ServiceProvider屬性,之后通過該屬性創建。由于是不同的IServiceScope對象,我們可以大膽的假設IServiceScope對象的ServiceProvider屬性也是不同的IServiceProvider對象。所以每個ServiceProvider對象內部,只需要維護一份注入對象的副本即可;由于IServiceScope對象實現了IDisposable接口(用在using上的對象,都實現了IDisposable接口,當using范圍結束后,會自動調用IDisposable的Dispose方法),但注入的對象緩存在IServiceScope的ServiceProvider屬性對象中,所以我們讓ServiceProvider類也實現IDisposable接口,在IServiceScope的Dispose方法內部調用ServiceProvider類的Dispose方法即可。

通過上面的分析,我們可以大致想象出ServiceProvider類的定義,下面就是ServiceProvider類縮減的源代碼:

internal class ServiceProvider : IServiceProvider, IDisposable    {        private readonly object _sync = new object();        private readonly ServiceProvider _root;        private readonly ServiceTable _table;        private readonly Dictionary<IService, object> _resolvedServices = new Dictionary<IService, object>();        private ConcurrentBag<IDisposable> _disposables = new ConcurrentBag<IDisposable>();        public ServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors)        {            _root = this;            _table = new ServiceTable(serviceDescriptors);            _table.Add(typeof(IServiceProvider), new ServiceProviderService());            _table.Add(typeof(IServiceScopeFactory), new ServiceScopeService());            _table.Add(typeof(IEnumerable<>), new OpenIEnumerableService(_table));        }        internal ServiceProvider(ServiceProvider parent)        {            _root = parent._root;            _table = parent._table;        }        public object GetService(Type serviceType);                public void Dispose()        {            var disposables = Interlocked.Exchange(ref _disposables, null);            if (disposables != null)            {                foreach (var disposable in disposables)                {                    disposable.Dispose();                }            }        }}

對于ServiceProvider對象共有5個屬性,

  • “_sync”是用于多線程同步的鎖對象,我們可以不關心。
  • ServiceTable的“_table”對象,是內部維護注入類關系的字典表。
  • resolvedServices是用于維護在該范圍內已經創建好的注入對象,當有該范圍內的對象,首先會判斷該字典表中是否存在實例,如果存在直接返回,不存在創建新的實例加入到該字典表中,并將該新創建的實例返回。
  • “disposables”是一個多線程支持的列表,從名字就看出這是調用Dispose后需要釋放的對象。從Dispose方法也可以認證這點。(當注入的對象是實現了IDisposable接口,就需要在使用結束后調用其Dispose方法將其使用的關鍵資源釋放掉,以免造成內存垃圾和資源浪費。)
  • ServiceProvider類型的“root”屬性,這個.....(我估計十有八九會問這是什么鬼?難道ServiceProvider也是鏈形結構?但是那也不能叫root啊?難道是Singleton的實現,但是為毛不是全局的,而且每個ServiceProvider都有這個副本呢??)。經過參考其簡單到鬼的注釋,和反復試驗發現確實是Singleton的實現。

ServiceProvider的Root屬性展開

首先我們剛才沒有注意到一個問題,就是ServiceProvider類定義不是public的,而是internal的。來我們回憶下類的定義:

internal class ServiceProvider : IServiceProvider, IDisposable

所以我們在外面是無法調用/構建ServiceProvider的實例的,只能在程序集范圍內實例話。那在哪些地方調用該類的構造函數呢?結果發現倆個構造函數都只被調用過一次。下面將調用的代碼列出:

public static class ServiceCollectionExtensions    {        public static IServiceProvider BuildServiceProvider(this IServiceCollection services)        {            return new ServiceProvider(services);        }    }internal class ServiceScopeFactory : IServiceScopeFactory    {        private readonly ServiceProvider _provider;        public ServiceScopeFactory(ServiceProvider provider)        {            _provider = provider;        }        public IServiceScope CreateScope()        {            return new ServiceScope(new ServiceProvider(_provider));        }    }
ServiceProvider構造函數
  • 對于ServiceCollectionExtensions類調用的構造函數:這是對于IServiceCollection接口(繼承自IList<ServiceDescriptor>)的擴展,實際就是用IServiceCollection對象創建出ServiceProvider對象供外面調用。這是微軟實現的依賴注入的入口。我們看使用IServiceCollection為參數的ServiceProvider
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 财经| 白水县| 大荔县| 汕头市| 隆回县| 九龙城区| 旬邑县| 黄梅县| 柘荣县| 金沙县| 纳雍县| 福清市| 彭泽县| 大城县| 聂拉木县| 丰都县| 永康市| 六盘水市| 邻水| 萝北县| 桃园县| 德庆县| 响水县| 南皮县| 泰兴市| 介休市| 贵溪市| 五寨县| 广灵县| 澄城县| 阿拉尔市| 鹤壁市| 辽宁省| 台中市| 横峰县| 香港| 甘德县| 抚宁县| 旬阳县| 宣武区| 寿阳县|