Net6 DI源码分析Part3 CallSiteRuntimeResolver,CallSiteVisitor
CallSiteRuntimeResolver
CallSiteRuntimeResolver
是实现了CallSiteVisitor之一。
提供的方法主要分三个部分
自有成员方法
- Resolve提供服务
- VisitCache
- 私有构造函数
重写父类方法
VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
调用父类VisitCallSiteMain ,并把创建出来的服务添加到context.Scope.CaptureDisposablereturn context.Scope.CaptureDisposable(VisitCallSiteMain(transientCallSite, context));
object VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
- 先找对应callSite.Value是否有值如果有直接返回
- 如果没有直接调用 VisitCallSiteMain创建服务并把对象rootServiceProviderEngine内。
- 创建的服务放入callSite.Value。
if (callSite.Value is object value)
{
return value;
} var lockType = RuntimeResolverLock.Root;
ServiceProviderEngineScope serviceProviderEngine = context.Scope.RootProvider.Root;
if (callSite.Value is object resolved)
{
return resolved;
}
resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
{
Scope = serviceProviderEngine,
AcquiredLocks = context.AcquiredLocks | lockType
});
serviceProviderEngine.CaptureDisposable(resolved);
callSite.Value = resolved;
return resolved;
VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
- 先去serviceProviderEngine.resolvedServices拿,有的话直接返回如果没拿到执行步骤2去创建。serviceProviderEngine.resolvedServices.TryGetValue(callSite.Cache.Key, out object resolved)
- VisitCallSiteMain创建对象
- 把创建后的对象加入对应Scope的 disposable列表
- 把创建后的对象加入对应Scope的 resolvedServices列表
if (resolvedServices.TryGetValue(callSite.Cache.Key, out object resolved))
{
return resolved;
}
resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
{
Scope = serviceProviderEngine,
AcquiredLocks = context.AcquiredLocks | lockType
});
serviceProviderEngine.CaptureDisposable(resolved);
resolvedServices.Add(callSite.Cache.Key, resolved);
return resolved;
实现父类抽象方法
- VisitConstructor
- 给构造方法提供参数(如果有参数递归调用VisitCallSite创建参数对象)
- 直接调用ServiceCallSite的ConstructorInfo反射创建对象。
object[] parameterValues;
if (constructorCallSite.ParameterCallSites.Length == 0)
{
parameterValues = Array.Empty<object>();
}
else
{
parameterValues = new object[constructorCallSite.ParameterCallSites.Length];
for (int index = 0; index < parameterValues.Length; index++)
{
parameterValues[index] = VisitCallSite(constructorCallSite.ParameterCallSites[index], context);
}
} return constructorCallSite.ConstructorInfo.Invoke(BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameterValues, culture: null);
- override object VisitConstant(ConstantCallSite constantCallSite, RuntimeResolverContext context)
直接返回CallSite对象的DefaultValue
return constantCallSite.DefaultValue;
- VisitServiceProvider
return context.Scope;
- override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
根据ServiceCallSites直接循环调用VisitCallSite创建实例,然后根据实例创建集合返回var array = Array.CreateInstance(
enumerableCallSite.ItemType,
enumerableCallSite.ServiceCallSites.Length);
for (int index = 0; index < enumerableCallSite.ServiceCallSites.Length; index++)
{
object value = VisitCallSite(enumerableCallSite.ServiceCallSites[index], context);
array.SetValue(value, index);
}
return array;
- VisitFactory
return factoryCallSite.Factory(context.Scope);
- VisitConstructor
体力活都给CallSiteFactory了
CallSiteVisitor
- 方法
VisitCallSite(ServiceCallSite callSite, TArgument argument)
- 保证Stack安全
- 根据callSite的Cache.Location去调用不同策略的Cache方法。
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();
}
VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
- 根据不同CallSiteKind去调用不同策略的创建服务方法。
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()));
}
- 根据不同CallSiteKind去调用不同策略的创建服务方法。
- 虚方法
- TResult VisitNoCache(ServiceCallSite callSite, TArgument argument) => VisitCallSiteMain(callSite, argument);
- TResult VisitDisposeCache(ServiceCallSite callSite, TArgument argument) -> isitCallSiteMain(callSite, argument);
- TResult VisitRootCache(ServiceCallSite callSite, TArgument argument) -> VisitCallSiteMain(callSite, argument);
- TResult VisitScopeCache(ServiceCallSite callSite, TArgument argument) => VisitCallSiteMain(callSite, argument);
根据生命周期策略由子类实现对应存储机制。
- 抽象方法
- TResult VisitConstructor(ConstructorCallSite constructorCallSite, TArgument argument);
- TResult VisitConstant(ConstantCallSite constantCallSite, TArgument argument);
- TResult VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, TArgument argument);
- TResult VisitIEnumerable(IEnumerableCallSite enumerableCallSite, TArgument argument);
- TResult VisitFactory(FactoryCallSite factoryCallSite, TArgument argument);
根据服务注册时的创建机制策略由子类实现对应的创建对象机制。
CallSiteVisitor负责这活怎么干!。CallSiteRuntimeResolver负责干活
- 调用 VisitCallSite在内部区分出scope并调用具体实现方法缓存方法 (CallSiteResultCacheLocation),
-> VisitCache方法
-> 但是在缓存前得先得到被缓存的对象,这时通过调用(VisitCallSiteMain)创建对象
-> VisitCallSiteMain根据提供的callsite类型去调用实现的抽象方法创建对应对象
-> 根据cache对应的方法缓存步骤1.1的结果。 - return cahce的结果。
整体的获取对象流程大约如下
CallSiteRuntimeResolver.Resolve -> CallSiteVisitor->VisitCallSite callSite.Cache.Location VisitRootCache/VisitScopeCache/ VisitDisposeCache/ VisitNoCache -> CallSiteRuntimeResolver.VisitCache/ VisitRootCache -> VisitRootCache -> CallSiteVisitor.VisitCallSiteMain 根据callSite.Kind CallSiteRuntimeResolver.VisitFactory(abstract TResult VisitFactory)递归调用 VisitCallSite
最新文章
- [LeetCode] Count and Say 计数和读法
- MySQL 常用的sql语句小结(待续)
- UML 类图常用表示方法.
- 我为什么要拒绝Ctrl+C和Ctrl+V?
- JZOJ 1312:关灯问题
- sdut 487-3279【哈希查找,sscanf ,map】
- RMQ(非log2储存方法)
- PL/SQL : Procedural Language / Structual Query Language and it is an exrension to SQL.
- Codeforces Round #120 (Div. 2)
- [转]应聘Java,jsp,j2ee软件工程师笔试中可能出现的问题
- [译]好程序员的五声&ldquo;呐喊&rdquo;
- sublime text 3.0使用
- delphi TOpenDialog
- 资源文件(.RES)的应用
- krpano音量控制(我们已经转移到krpano中国网站 krpano360.com)
- 使用Idea作为go的IDE
- 自建Nuget服务器
- Delphi 字符串转日期,强大到窒息,VarToDateTime 解决了 困扰很久的小问题
- iOS Runtime的消息转发机制
- cgi、fastcgi及php-fpm分别是什么