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

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

[Asp.net 5] DependencyInjection項目代碼分析4-微軟的實現(5)(IEnumerable<>補充)

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

[asp.net 5] DependencyInjection項目代碼分析4-微軟的實現(5)(IEnumerable<>補充)

Asp.net 5的依賴注入注入系列可以參考鏈接: [Asp.net 5] DependencyInjection項目代碼分析-目錄

我們在之前講微軟的實現時,對于OpenIEnumerableService與ClosedIEnumerableService拋下沒講,現在我們就將該部分補充完整。

我們回憶ServicePRovider類的構造函數(對外部使用的)中,注冊了IEnumerable<>、new OpenIEnumerableService(_table)的關系。

        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));        }
ServiceProvider構造函數

因為IEnumerable是泛型,所以我們可以推斷OpenIEnumerableService類應該實現IGenericService接口。那么如果我們想查找IEnumerable<T>的實現類中間會有怎樣的過程呢?

  • [步驟1]首先系統會查找在ServiceTable內部_services(Dictionary<Type, ServiceEntry>類型)是否有注冊過IEnumerable<T>類型,如果有注冊直接返回實現類中最后一個。下面是直接包含IEnumerable<T>的原因
    • 系統可以顯示的注冊IEnumerable<T>,比如services.AddTransient<IEnumerable<T>, List<T>>();
    • 系統也可能之前獲取過IEnumerable<T>,所以_services中有上次結果的緩存。
  • [步驟2]如果沒有找到相應的IEnumerable<T>,系統會繼續通過_genericServices(Dictionary<Type, List<IGenericService>>類型)查找IEnumerable<>,與通過_services方式獲取不同,通過_genericServices會獲取到的是所有注冊過IEnumerable<>類型對應的IGenericService列表(List類型,包含順序)并不是單一一個IGenericService;之后順序遍歷IGenericService列表,將IEnumerable<T>/IGenericService.GetService()的對應關系添加到services中,重復[步驟1]的操作獲取。
    • 如果系統沒額外注冊IEnumerable<>類型,那么_genericServices的列表中只能獲取唯一的注冊項OpenIEnumerableService,那么相應的操作則在OpenIEnumerableService中進行。
    • 如果系統額外注冊IEnumerable<>類型(假設為GenericService1),那么在注冊列表中GenericService1一定排在OpenIEnumerableService之后。所以當獲取IEnumerable<T>時,OpenIEnumerableService.GetService()與GenericService1.GetService()返回值一定都會添加到_services中,但是GenericService1.GetService()一定在后面,所以IEnumerable<T>的實現類一定是GenericService1.GetService().CreateCallSite().Invoke()的值;換句話說GenericService1會將OpenIEnumerableService覆蓋掉。
    • 由于注冊IEnumerable<>會覆蓋掉OpenIEnumerableService,所以原則上不允許注冊IEnumerable<>類型

OpenIEnumerableService與ClosedIEnumerableService

由于OpenIEnumerableService實現IGenericService接口,所以會返回IService類型的對象,該對象是ClosedIEnumerableService類型。ClosedIEnumerableService類型內部實際上返回的是ServiceTable中_services所有T的注冊項,之后以IEnumerable<T>類型返回。

    internal class OpenIEnumerableService : IGenericService    {        private readonly ServiceTable _table;        public OpenIEnumerableService(ServiceTable table)        {            _table = table;        }        public ServiceLifetime Lifetime        {            get { return ServiceLifetime.Transient; }        }        public IService GetService(Type closedServiceType)        {            var itemType = closedServiceType.GetTypeInfo().GenericTypeArguments[0];            ServiceEntry entry;            return _table.TryGetEntry(itemType, out entry) ?                new ClosedIEnumerableService(itemType, entry) :                null;        }    }
OpenIEnumerableService
    internal class ClosedIEnumerableService : IService    {        private readonly Type _itemType;        private readonly ServiceEntry _serviceEntry;        public ClosedIEnumerableService(Type itemType, ServiceEntry entry)        {            _itemType = itemType;            _serviceEntry = entry;        }        public IService Next { get; set; }        public ServiceLifetime Lifetime        {            get { return ServiceLifetime.Transient; }        }        public IServiceCallSite CreateCallSite(ServiceProvider provider, ISet<Type> callSiteChain)        {            var list = new List<IServiceCallSite>();            for (var service = _serviceEntry.First; service != null; service = service.Next)            {                list.Add(provider.GetResolveCallSite(service, callSiteChain));            }            return new CallSite(_itemType, list.ToArray());        }        private class CallSite : IServiceCallSite        {            private readonly Type _itemType;            private readonly IServiceCallSite[] _serviceCallSites;            public CallSite(Type itemType, IServiceCallSite[] serviceCallSites)            {                _itemType = itemType;                _serviceCallSites = serviceCallSites;            }            public object Invoke(ServiceProvider provider)            {                var array = Array.CreateInstance(_itemType, _serviceCallSites.Length);                for (var index = 0; index != _serviceCallSites.Length; ++index)                {                    array.SetValue(_serviceCallSites[index].Invoke(provider), index);                }                return array;            }            public Expression Build(Expression provider)            {                return Expression.NewArrayInit(                    _itemType,                    _serviceCallSites.Select(callSite =>                        Expression.Convert(                            callSite.Build(provider),                            _itemType)));            }        }    }
ClosedIEnumerableService

[之前我們介紹ServiceEntry時,明確指出是鏈表結構,而不是單獨存放一個值;其應用在這進行了淋漓盡致的表現]


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 三原县| 喜德县| 辽源市| 富川| 延吉市| 墨竹工卡县| 余干县| 方正县| 崇阳县| 襄汾县| 淮滨县| 乐昌市| 德化县| 新巴尔虎左旗| 沙坪坝区| 隆子县| 潮安县| 高尔夫| 巫山县| 吴忠市| 民权县| 黄龙县| 视频| 永德县| 偏关县| 巴林左旗| 宾川县| 榆中县| 九龙坡区| 道孚县| 石棉县| 鹤山市| 泰安市| 北票市| 酒泉市| 驻马店市| 武冈市| 高台县| 晋州市| 集贤县| 徐州市|