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>的實現類中間會有怎樣的過程呢?
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時,明確指出是鏈表結構,而不是單獨存放一個值;其應用在這進行了淋漓盡致的表現]
新聞熱點
疑難解答