DependencyInjection概述
ServiceIdentifier
internal readonly struct ServiceIdentifier : IEquatable<ServiceIdentifier> {
// service的key标识
public object? ServiceKey { get; }
// service的类型
public Type ServiceType { get; }
//创建 携带key标识的service的身份证
public static ServiceIdentifier FromDescriptor(ServiceDescriptor serviceDescriptor)
=> new ServiceIdentifier(serviceDescriptor.ServiceKey, serviceDescriptor.ServiceType);
//创建 不ey标识的service的身份证
public static ServiceIdentifier FromServiceType(Type type) => new ServiceIdentifier(null, type);
public ServiceIdentifier(Type serviceType){
ServiceType = serviceType;
}
public ServiceIdentifier(object? serviceKey, Type serviceType){
ServiceKey = serviceKey; ServiceType = serviceType;
}
public ServiceIdentifier GetGenericTypeDefinition() => new ServiceIdentifier(ServiceKey, ServiceType.GetGenericTypeDefinition());
}
服务身份证:身份证构成 serviceKey(key标识) + serviceType
ServiceDescriptorCacheItem
private struct ServiceDescriptorCacheItem{
//这里存储的是 同一个ServiceIdentifier的多个实现时,第一个注册进来的值
private ServiceDescriptor? _item;
//存储 同一个ServiceIdentifier的多个实现,并添加到一起,而他们的顺序就是他们在ServiceCacheKey中的slot(槽位)
private List<ServiceDescriptor>? _items;
public ServiceDescriptor Last{
get{
if (_items != null && _items.Count > 0){
return _items[_items.Count - 1];
}
return _item;
}
}
public int Count{
get{
if (_item == null){
return 0;
}
return 1 + (_items?.Count ?? 0);
}
}
public ServiceDescriptor this[int index]{
get{
if (index >= Count){
throw new ArgumentOutOfRangeException(nameof(index));
}
if (index == 0){
return _item!;
}
return _items![index - 1];
}
}
public int GetSlot(ServiceDescriptor descriptor)
{
if (descriptor == _item){
return Count - 1;
}
if (_items != null){
int index = _items.IndexOf(descriptor);
if (index != -1){
return _items.Count - (index + 1);
}
}
throw new InvalidOperationException(SR.ServiceDescriptorNotExist);
}
public ServiceDescriptorCacheItem Add(ServiceDescriptor descriptor){
var newCacheItem = default(ServiceDescriptorCacheItem);
if (_item == null){
newCacheItem._item = descriptor;
}
else{
newCacheItem._item = _item;
newCacheItem._items = _items ?? new List<ServiceDescriptor>();
newCacheItem._items.Add(descriptor);
}
return newCacheItem;
}
}
}
通过 ServiceDescriptor 中的 ServiceKey 和 ServiceType 去创建出 ServiceIdentifier,再根据ServiceIdentifier是否相同,将相同的ServiceIdentifier的ServiceDescriptor存放在ServiceDescriptorCacheItem中的list集合中,而list集合中的存放顺序实际上就是 ServiceCacheKey上对应的槽位。
ServiceCacheKey
internal readonly struct ServiceCacheKey : IEquatable<ServiceCacheKey> {
public ServiceIdentifier ServiceIdentifier { get; }
/// 对于同一个 ServiceIdentifier 中有多个实现类
/// For example for service collection
/// IService Impl1
/// IService Impl2
/// IService Impl3
/// We would get the following cache keys:
/// Impl1 2
/// Impl2 1
/// Impl3 0
/// </summary>
public int Slot { get; }
public ServiceCacheKey(object key, Type type, int slot){
ServiceIdentifier = new ServiceIdentifier(key, type);
Slot = slot;
}
public ServiceCacheKey(ServiceIdentifier type, int slot){
ServiceIdentifier = type;
Slot = slot;
}
}
小结
ServiceIdentifier = ServiceDescriptor.serviceKey + ServiceDescriptor.serviceType
ServiceCacheKey = ServiceIdentifier + slot( List.index位置)
ServiceDescriptorCacheItem = List + List[0]
ServiceCallSite(服务调用站点)
internal abstract class ServiceCallSite{
protected ServiceCallSite(ResultCache cache){
Cache = cache;
}
//服务的类型
public abstract Type ServiceType { get; }
//服务的实现可续
public abstract Type? ImplementationType { get; }
//调用站点类型
public abstract CallSiteKind Kind { get; }
//服务的生命周期,serviceIdentifier(服务身份证)以及服务所在ServiceDescriptorCacheItem-list的位置
public ResultCache Cache { get; }
//单例储存的地方
public object? Value { get; set; }
public object? Key { get; set; }
}
ConstantCallSite
CallSiteFacory.TryCreateExact方法中可知:
if (descriptor.HasImplementationInstance()){ callSite = new ConstantCallSite(descriptor.ServiceType, descriptor.GetImplementationInstance()); }
//descriptor.HasImplementationInstance()方法最终来到此进行判断,就是判断是否以及存在service的实例 public static object? GetImplementationInstance(this ServiceDescriptor serviceDescriptor) { return serviceDescriptor.IsKeyedService ? serviceDescriptor.KeyedImplementationInstance : serviceDescriptor.ImplementationInstance; }
- 由上可知:
- ConstantCallSite应用与 serviceDescription 中_implementationInstance不为空的情况
- 而_implementationInstance不为空的话,说明该服务调用站点的生命周期为单例,因为在构建服务的时候如果传了服务类型对应的实例对象的话,则为单例,在DependencyInjection.Abstractions可得
ConstructorCallSite
CallSiteFacory.TryCreateExact方法中可知:
else if (descriptor.HasImplementationType()){ callSite = CreateConstructorCallSite(lifetime, serviceIdentifier, descriptor.GetImplementationType()!, callSiteChain); }
public static Type? GetImplementationType(this ServiceDescriptor serviceDescriptor){ return serviceDescriptor.IsKeyedService ? serviceDescriptor.KeyedImplementationType : serviceDescriptor.ImplementationType; }
- 由上可知:
- ConstructorCallSite 应用与 serviceDescription 中 _implementationType不为空的情况
FactoryCallSite
CallSiteFacory.TryCreateExact方法中可知:
else if (!descriptor.IsKeyedService && descriptor.ImplementationFactory != null){ callSite = new FactoryCallSite(lifetime, descriptor.ServiceType, descriptor.ImplementationFactory); } else if (descriptor.IsKeyedService && descriptor.KeyedImplementationFactory != null){ callSite = new FactoryCallSite(lifetime, descriptor.ServiceType, serviceIdentifier.ServiceKey!, descriptor.KeyedImplementationFactory); }
- 由上可知:
- FactoryCallSite 应用与 serviceDescription 中 _implementationFactory 不为空的情况
IEnumerableCallSite
CallSiteFacory.CreateCallSite方法中可知:
private ServiceCallSite? CreateCallSite(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain){ var callsiteLock = _callSiteLocks.GetOrAdd(serviceIdentifier, static _ => new object()); lock (callsiteLock){ callSiteChain.CheckCircularDependency(serviceIdentifier); ServiceCallSite? callSite = TryCreateExact(serviceIdentifier, callSiteChain) ?? TryCreateOpenGeneric(serviceIdentifier, callSiteChain) ??TryCreateEnumerable(serviceIdentifier, callSiteChain); eturn callSite; } }
TryCreateExact 是尝试匹配准确类型,TryCreateOpenGeneric 是尝试匹配泛型类型,TryCreateEnumerable则是尝试匹配IEnumerable类型。
当 serviceProvider.getservice<IEnumerable>() 或serviceProvider.getservice(IEnumerable)时,再TryCreateExact和TryCreateOpenGeneric中会无法匹配上,从而执行到TryCreateEnumerable,去创建IEnumerable的调用站点。
CallSiteFactory(服务调用站点总站)
internal sealed class CallSiteFactory : IServiceProviderIsService, IServiceProviderIsKeyedService{
private const int DefaultSlot = 0;
//存储了serviceCollection中所有的ServiceDescriptor
private readonly ServiceDescriptor[] _descriptors;
//缓存了 ServiceIdentifier 对应ServiceDescriptorCacheItem的Items中Item的服务调用节点
private readonly ConcurrentDictionary<ServiceCacheKey, ServiceCallSite> _callSiteCache = new ConcurrentDictionary<ServiceCacheKey, ServiceCallSite>();
//缓存了 ServiceIdentifier对应的ServiceDescriptorCacheItem
private readonly Dictionary<ServiceIdentifier, ServiceDescriptorCacheItem> _descriptorLookup = new Dictionary<ServiceIdentifier, ServiceDescriptorCacheItem>();
//缓存了ServiceIdentifier的对象锁
private readonly ConcurrentDictionary<ServiceIdentifier, object> _callSiteLocks = new ConcurrentDictionary<ServiceIdentifier, object>();
//栈守卫
private readonly StackGuard _stackGuard;
}
- 负责创建和缓存所有的Service
CallSite
- 存储了serviceCollection中所有的ServiceDescriptor
- 对ServiceDescriptor进行了分类,serviceKey以及serviceType相同的ServiceDescriptor的会被归在同一个类链条上(实际上也不算是链条)
- 缓存了所有 ServiceIdentifier + solt 对应的 服务调用站点
ServiceProvider
public sealed class ServiceProvider : IServiceProvider, IKeyedServiceProvider, IDisposable, IAsyncDisposable{
//服务获取站点校验器
private readonly CallSiteValidator? _callSiteValidator;
// 创建ServiceAccessor(服务访问者)的委托
private readonly Func<ServiceIdentifier, ServiceAccessor> _createServiceAccessor;
//创建ServiceAccessor(服务访问者)引擎
internal ServiceProviderEngine _engine;
// 存储对应ServiceIdentifier对应的ServiceAccessor(服务访问者)
private readonly ConcurrentDictionary<ServiceIdentifier, ServiceAccessor> _serviceAccessors;
//用于创建和缓存服务的调用站点
internal CallSiteFactory CallSiteFactory { get; }
//用于 root 的生命周期管理
internal ServiceProviderEngineScope Root { get; }
}
DefaultServiceProviderFactory
DefaultServiceProviderFactory是IServiceProviderFactory的默认实现类
public class DefaultServiceProviderFactory : IServiceProviderFactory<IServiceCollection>{ private readonly ServiceProviderOptions _options; public DefaultServiceProviderFactory() : this(ServiceProviderOptions.Default){ } public DefaultServiceProviderFactory(ServiceProviderOptions options){ _options = options ?? throw new ArgumentNullException(nameof(options)); } public IServiceCollection CreateBuilder(IServiceCollection services){ return services; } public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder){ return containerBuilder.BuildServiceProvider(_options); } }
ServiceProviderEngineScope
- ServiceProviderEngineScope为ServiceProvider提供作用域的能力
- scope服务的生命周期的存储位置
internal sealed class ServiceProviderEngineScope : IServiceScope, IServiceProvider, IKeyedServiceProvider, IAsyncDisposable, IServiceScopeFactory{ internal IList<object> Disposables => _disposables ?? (IList<object>)Array.Empty<object>(); //是否进行了释放 private bool _disposed; //scope生命周期的服务 和 实现了IDisposable接口的瞬时生命周期服务 都会被加入到此处,便于释放对象 private List<object>? _disposables; public ServiceProviderEngineScope(ServiceProvider provider, bool isRootScope){ ResolvedServices = new Dictionary<ServiceCacheKey, object?>(); RootProvider = provider; IsRootScope = isRootScope; } //scope生命周期服务的内存存储位置 internal Dictionary<ServiceCacheKey, object?> ResolvedServices { get; } //是否是root作用域 public bool IsRootScope { get; } //不管是root作用域,还是非root作用,在同一个serviceProvider下创建的作用域,都是同一个ServiceProvider internal ServiceProvider RootProvider { get; } //创建非root作用域 public IServiceScope CreateScope() => RootProvider.CreateScope(); }
ServiceProviderEngine
internal abstract class ServiceProviderEngine{ public abstract Func<ServiceProviderEngineScope, object?> RealizeService(ServiceCallSite callSite); } }
- 这个类的职责就是创建服务【传入作用域,解析服务】。
- 也是吧服务作用域与服务调用站点进行了解耦
DynamicServiceProviderEngine
internal sealed class DynamicServiceProviderEngine : CompiledServiceProviderEngine{ private readonly ServiceProvider _serviceProvider; public DynamicServiceProviderEngine(ServiceProvider serviceProvider) : base(serviceProvider){ _serviceProvider = serviceProvider; } public override Func<ServiceProviderEngineScope, object?> RealizeService(ServiceCallSite callSite){ int callCount = 0; return scope =>{ //返回真正创建对应服务的委托方法 var result = CallSiteRuntimeResolver.Instance.Resolve(callSite, scope); if (Interlocked.Increment(ref callCount) == 2){ _ = ThreadPool.UnsafeQueueUserWorkItem(_ =>{ try{ //如果当前是第二次调用,则调用父级进行缓存 _serviceProvider.ReplaceServiceAccessor(callSite, base.RealizeService(callSite)); } catch (Exception ex){ //....... } },null); } return result; }; } }
DynamicServiceProviderEngine就是把真正创建服务的方法进行了一层包装,生成委托方法,并且启用线程
CallSiteVisitor
- 服务调用站点访客,从这个类作为中转类。
- 转到Root,scope,顺序作用域去做服务的缓存操作
- 转到构建对应服务的
ServiceCallSite
internal abstract class CallSiteVisitor<TArgument, TResult>{ protected virtual TResult VisitCallSite(ServiceCallSite callSite, TArgument argument){ //... switch (callSite.Cache.Location){ case CallSiteResultCacheLocation.Root: return VisitRootCache(callSite, argument); case CallSiteResultCacheLocation.Scope: return VisitScopeCache(callSite, argument); case CallSiteResultCacheLocation.Dispose: return VisitDisposeCache(callSite, argument); case CallSiteResultCacheLocation.None: return VisitNoCache(callSite, argument); default: throw new ArgumentOutOfRangeException(); } } protected virtual TResult VisitCallSiteMain(ServiceCallSite callSite, TArgument argument){ switch (callSite.Kind) { case CallSiteKind.Factory: return VisitFactory((FactoryCallSite)callSite, argument); case CallSiteKind.IEnumerable: return VisitIEnumerable((IEnumerableCallSite)callSite, argument); case CallSiteKind.Constructor: return VisitConstructor((ConstructorCallSite)callSite, argument); case CallSiteKind.Constant: return VisitConstant((ConstantCallSite)callSite, argument); case CallSiteKind.ServiceProvider: return VisitServiceProvider((ServiceProviderCallSite)callSite, argument); default: throw new NotSupportedException(SR.Format(SR.CallSiteTypeNotSupported, callSite.GetType())); } } protected virtual TResult VisitNoCache(ServiceCallSite callSite, TArgument argument){ return VisitCallSiteMain(callSite, argument); } protected virtual TResult VisitDisposeCache(ServiceCallSite callSite, TArgument argument){ return VisitCallSiteMain(callSite, argument); } protected virtual TResult VisitRootCache(ServiceCallSite callSite, TArgument argument){ return VisitCallSiteMain(callSite, argument); } protected virtual TResult VisitScopeCache(ServiceCallSite callSite, TArgument argument){ return VisitCallSiteMain(callSite, argument); } protected abstract TResult VisitConstructor(ConstructorCallSite constructorCallSite, TArgument argument); protected abstract TResult VisitConstant(ConstantCallSite constantCallSite, TArgument argument); protected abstract TResult VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, TArgument argument); protected abstract TResult VisitIEnumerable(IEnumerableCallSite enumerableCallSite, TArgument argument); protected abstract TResult VisitFactory(FactoryCallSite factoryCallSite, TArgument argument); }
CallSiteRuntimeResolver
CallSiteRuntimeResolver是CallSiteVisitor的默认实现:主要是实现了不同的生命周期的服务,存储到对应生命周期的位置。
Q&A
(1)如何解决非Root作用域释放导致单例生命周期对象中引入的非Root作用域的Scope生命周期对象释放问题?
public static void Main(string[] args){ IServiceCollection services = new ServiceCollection(); services.AddSingleton<DemoTwo>(); services.AddScoped<DemoOne>(provider => new() { Id = 1, Name = "binbinbin", Sex = "man" }); IServiceProvider serviceProvider = services.BuildServiceProvider(); DemoTwo demoTwo = null; using (IServiceScope serviceScope = serviceProvider.CreateScope()){ demoTwo = serviceScope.ServiceProvider.GetService<DemoTwo>(); Console.WriteLine("not RootScope DemoTwo Hashcode:" + demoTwo.GetHashCode()); Console.WriteLine("not RootScope DemoTwo GetDemoOne" + demoTwo.GetDemoOne()); } demoTwo = serviceProvider.GetService<DemoTwo>(); Console.WriteLine("RootScope DemoTwo Hashcode:" + demoTwo.GetHashCode()); Console.WriteLine("RootScope DemoTwo GetDemoOne" + demoTwo.GetDemoOne()); using (IServiceScope serviceScope = serviceProvider.CreateScope()){ demoTwo = serviceScope.ServiceProvider.GetService<DemoTwo>(); Console.WriteLine("not RootScope DemoTwo Hashcode:" + demoTwo.GetHashCode()); Console.WriteLine("not RootScope DemoTwo GetDemoOne" + demoTwo.GetDemoOne()); } public class DemoOne{ public int Id { get; set; } public string Name { get; set; } public string Sex { get; set; } } public class DemoTwo{ private readonly DemoOne _demoOne; public DemoTwo(DemoOne demoOne){ _demoOne = demoOne; } public string GetDemoOne(){ return _demoOne.GetHashCode() + ""; } } }
先往serviceCollection中注册Scoped生命周期的DemoOne以及单例的DemoTwo,DemoTwo中依赖注入DemoOne
然后创建serviceProvider,注意创建serviceProvider,并不会创建DemoOne以及DemoTwo对应的ServiceCallSite以及他们的创建委托方法。但是注意的是,在另开了一个非root作用域(注意:DemoOne是scope作用域)里,
GetService``DemoOne
服务,但是DemoOne
是单例的,但是DemoOne
的注入参数是scope生命周期
,那如果释放了该作用域,那单例再去使用该参数岂不是会有问题!,那默认di中是如何解决这个问题的:提升作用域。从下代码可得:
protected override object? VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context){ return context.Scope.IsRootScope ? VisitRootCache(callSite, context) :VisitCache(callSite, context, context.Scope, RuntimeResolverLock.Scope); }
VisitScopeCache这里是对scope生命周期的服务进行缓存,如果这个服务是scope生命周期并且被依赖注入到单例的服务中,他的生命周期就会被提升。
(2)如何解决避免循环依赖的问题?
默认di中主要是依靠这条链子(
CallSiteChain
)去完成循环依赖的检测:internal sealed class CallSiteChain{ private readonly Dictionary<ServiceIdentifier, ChainItemInfo> _callSiteChain; public CallSiteChain(){ _callSiteChain = new Dictionary<ServiceIdentifier, ChainItemInfo>(); } //..... private readonly struct ChainItemInfo{ public int Order { get; } public Type? ImplementationType { get; } public ChainItemInfo(int order, Type? implementationType){ Order = order; ImplementationType = implementationType; } } }
循环依赖检测位置:
private ServiceCallSite? CreateCallSite(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain){ if (!_stackGuard.TryEnterOnCurrentStack()){ return _stackGuard.RunOnEmptyStack(CreateCallSite, serviceIdentifier, callSiteChain); } // We need to lock the resolution process for a single service type at a time: // Consider the following: // C -> D -> A // E -> D -> A // Resolving C and E in parallel means that they will be modifying the callsite cache concurrently // to add the entry for C and E, but the resolution of D and A is synchronized // to make sure C and E both reference the same instance of the callsite. // This is to make sure we can safely store singleton values on the callsites themselves var callsiteLock = _callSiteLocks.GetOrAdd(serviceIdentifier, static _ => new object()); lock (callsiteLock){ //循环依赖检测 callSiteChain.CheckCircularDependency(serviceIdentifier); ServiceCallSite? callSite = TryCreateExact(serviceIdentifier, callSiteChain) ??TryCreateOpenGeneric(serviceIdentifier, callSiteChain) ?? TryCreateEnumerable(serviceIdentifier, callSiteChain); return callSite; } }
循环依赖添加:在
TryCreateExact
和TryCreateOpenGeneric
和TryCreateEnumerable
方法中会有对应的循环依赖链条添加和检测
(3)关于GetService<IEnumerable<xxxx>>
中IEnumerable
的生命周期
直接上源码,直接看到在哪构建IEnumerable的服务的地方,也就是
TryCreateEnumerable#CallSiteFactory
//GetService调用情况一: GetService<IEnumerable<Demo>> //GetService调用情况二: GetService<IEnumerable<ITest<Demo>>> private ServiceCallSite? TryCreateEnumerable( ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain){ //DefaultSlot默认等于0(传进来的会先是0),Slot有什么用?其实就是获取ServiceDescriptorCacheItem._items[Slot] ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceIdentifier, DefaultSlot); //尝试获取缓存中的ServiceCallSite if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite? serviceCallSite)){ return serviceCallSite; } try { //处理循环依赖问题 callSiteChain.Add(serviceIdentifier); //获取调用GetService中的泛型参数 var serviceType = serviceIdentifier.ServiceType; //判断调用GetService中的泛型参数的泛型定义是否是IEnumerable<>, if (!serviceType.IsConstructedGenericType || serviceType.GetGenericTypeDefinition() != typeof(IEnumerable<>)){ return null; } //获取IEnumerable<>中的第一个泛型参数 Type itemType = serviceType.GenericTypeArguments[0]; //创建他的ServiceIdentifier var cacheKey = new ServiceIdentifier(serviceIdentifier.ServiceKey, itemType); //.... CallSiteResultCacheLocation cacheLocation = CallSiteResultCacheLocation.Root; ServiceCallSite[] callSites; //判断调用GetService中的泛型参数的IEnumerable<>中的第一个泛型参数是否是 可构造的泛型类型 //什么是可构造的泛型类型,比如 ITest<DemoOne>,Test<DemoOne>就是可构造的泛型类型 //如果不是可构造的泛型类型,就进入if中,因为如果他不是可构造的泛型类型,说明可以直调用精确类型来构造就行 //并且拿出_descriptorLookup中对应储存的 cacheKey 的那条链条ServiceDescriptorCacheItem if (!itemType.IsConstructedGenericType && !KeyedService.AnyKey.Equals(cacheKey.ServiceKey) && _descriptorLookup.TryGetValue(cacheKey, out ServiceDescriptorCacheItem descriptors)){ callSites = new ServiceCallSite[descriptors.Count]; for (int i = 0; i < descriptors.Count; i++){ ServiceDescriptor descriptor = descriptors[i]; //从链尾开始取对应的ServiceCallSite int slot = descriptors.Count - i - 1; //创建链条上对应注册服务的ServiceCallSite ServiceCallSite? callSite = TryCreateExact(descriptor, cacheKey, callSiteChain, slot); Debug.Assert(callSite != null); //比较每个ServiceCallSite的作用域,取最小的作用域 //比如: 注册了DemoOne的两个类:DemoOne,DemoOne,DemoOne的生命周期是单例,DemoOne的生命周期是瞬时,那么IEnumerable<DemoOne>的生命周期就是瞬时 cacheLocation = GetCommonCacheLocation(cacheLocation, callSite.Cache.Location); callSites[i] = callSite; } } else{ List<KeyValuePair<int, ServiceCallSite>> callSitesByIndex = new(); int slot = 0; for (int i = _descriptors.Length - 1; i >= 0; i--){ //比较 _descriptors 中的ServiceKey和 调用GetService中的泛型参数的IEnumerable<>中的第一个泛型参数 是否相同 if (KeysMatch(_descriptors[i].ServiceKey, cacheKey.ServiceKey)){ if (TryCreateExact(_descriptors[i], cacheKey, callSiteChain, slot) is { } callSite){ AddCallSite(callSite, i); } } } // for (int i = _descriptors.Length - 1; i >= 0; i--){ //比较 _descriptors 中的ServiceKey和 调用GetService中的泛型参数的IEnumerable<>中的第一个泛型参数 是否相同 if (KeysMatch(_descriptors[i].ServiceKey, cacheKey.ServiceKey)){ if (TryCreateOpenGeneric( _descriptors[i], cacheKey, callSiteChain, slot, throwOnConstraintViolation: false) is { } callSite){ AddCallSite(callSite, i); } } } callSitesByIndex.Sort((a, b) => a.Key.CompareTo(b.Key)); callSites = new ServiceCallSite[callSitesByIndex.Count]; for (var i = 0; i < callSites.Length; ++i){ callSites[i] = callSitesByIndex[i].Value; } void AddCallSite(ServiceCallSite callSite, int index){ slot++; //比如: 注册了ITest<>的两个实现类:Test<>,TestTest(),Test的生命周期是单例,TestTest的生命周期是瞬时,那么IEnumerable<ITest<xxx>>的生命周期就是瞬时 cacheLocation = GetCommonCacheLocation(cacheLocation, callSite.Cache.Location); callSitesByIndex.Add(new(index, callSite)); } } ResultCache resultCache = (cacheLocation == CallSiteResultCacheLocation.Scope || cacheLocation == CallSiteResultCacheLocation.Root) ? new ResultCache(cacheLocation, callSiteKey) : new ResultCache(CallSiteResultCacheLocation.None, callSiteKey); return _callSiteCache[callSiteKey] = new IEnumerableCallSite(resultCache, itemType, callSites); } finally{ callSiteChain.Remove(serviceIdentifier); } }
从上面可得,
IEnumerable
的生命周期的生命周期取决于,注册到serviceCollection中同一类型的ServiceKey的所有服务的生命周期范围的最小范围。那GetService<IEnumerable>应该如何使用呢?
public static void Main(string[] args){ IServiceCollection services = new ServiceCollection(); services.Add(ServiceDescriptor.Singleton(typeof(DemoOne), typeof(DemoOne))); services.Add(ServiceDescriptor.Singleton(typeof(DemoOne), typeof(DemoOne))); //Test,TestTests实现了ITest接口 services.Add(ServiceDescriptor.Singleton(typeof(ITest<>), typeof(Test<>))); services.Add(ServiceDescriptor.Singleton(typeof(ITest<>), typeof(TestTest<>))); var serviceFactory = new DefaultServiceProviderFactory(); IServiceProvider serviceProvider = serviceFactory.CreateServiceProvider(services); var demo1 = serviceProvider.GetService<IEnumerable<ITest<DemoOne>>>().ToList(); Console.WriteLine(demo1.Count); // 输出:2 var demo2 = serviceProvider.GetService<IEnumerable<DemoOne>>().ToList(); Console.WriteLine(demo2.Count); // 输出:2 }
(4)相同类型服务注册多个,会不会多个都生效呢?
已知,
GetService
方法拿三种类型的服务:
准确型参数
泛型参数
IEnumerable<>
参数
IEnumerable<精确型参数>
参数
IEnumerable<泛型参数>
参数问题三中已经说了使用
GetService()
获取IEnumerable<>
参数。准确型参数可看一下代码:
private ServiceCallSite? TryCreateExact( ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain){ //看过我前面博客的就知道ServiceDescriptorCacheItem是什么 if (_descriptorLookup.TryGetValue(serviceIdentifier, out ServiceDescriptorCacheItem descriptor)){ //这里descriptor.Last 相当于取了 ServiceDescriptorCacheItem 中的 _items.last,就是取了最后一个注册进来的服务 return TryCreateExact(descriptor.Last, serviceIdentifier, callSiteChain, DefaultSlot); } if (serviceIdentifier.ServiceKey != null){ var catchAllIdentifier = new ServiceIdentifier(KeyedService.AnyKey, serviceIdentifier.ServiceType); if (_descriptorLookup.TryGetValue(catchAllIdentifier, out descriptor)){ //这里descriptor.Last 相当于取了 ServiceDescriptorCacheItem 中的 _items.last,就是取了最后一个注册进来的服务 return TryCreateExact(descriptor.Last, serviceIdentifier, callSiteChain, DefaultSlot); } } return null; }
泛型参数可看一下代码:
private ServiceCallSite? TryCreateOpenGeneric( ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain){ if (serviceIdentifier.IsConstructedGenericType){ var genericIdentifier = serviceIdentifier.GetGenericTypeDefinition(); if (_descriptorLookup.TryGetValue(genericIdentifier, out ServiceDescriptorCacheItem descriptor)){ //这里descriptor.Last 相当于取了 ServiceDescriptorCacheItem 中的 _items.last,就是取了最后一个注册进来的服务 return TryCreateOpenGeneric(descriptor.Last, serviceIdentifier, callSiteChain, DefaultSlot, true); } if (serviceIdentifier.ServiceKey != null){ var catchAllIdentifier = new ServiceIdentifier(KeyedService.AnyKey, genericIdentifier.ServiceType); if (_descriptorLookup.TryGetValue(catchAllIdentifier, out descriptor)){ //这里descriptor.Last 相当于取了 ServiceDescriptorCacheItem 中的 _items.last,就是取了最后一个注册进来的服务 return TryCreateOpenGeneric(descriptor.Last, serviceIdentifier, callSiteChain, DefaultSlot, true); } } } return null; }
由此可得:使用
GetService
方法拿 准确型参数以及泛型参数的服务是只会取最后一次注册的那个服务的。