日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable补充)

發(fā)布時間:2023/12/18 编程问答 63 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable补充) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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

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

我們回憶ServiceProvider類的構造函數(shù)(對外部使用的)中,注冊了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構造函數(shù)

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

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

OpenIEnumerableService與ClosedIEnumerableService

由于OpenIEnumerableService實現(xiàn)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時,明確指出是鏈表結構,而不是單獨存放一個值;其應用在這進行了淋漓盡致的表現(xiàn)]

轉載于:https://www.cnblogs.com/watermoon2/p/4558837.html

總結

以上是生活随笔為你收集整理的[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable补充)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。