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