|
上一节聊了一下 CallSite 是怎样生成的,这一节我们来看一下 CallSite 是如何使用的。
入口
先让我们来回顾一下 CreateServiceAccessor 这个方法。- private Func<ServiceProviderEngineScope, object?> CreateServiceAccessor(Type serviceType)
- {
- //通过 服务类型 获取 callSite
- ServiceCallSite? callSite = CallSiteFactory.GetCallSite(serviceType, new CallSiteChain());
- if (callSite != null)
- {
- if (callSite.Cache.Location == CallSiteResultCacheLocation.Root)
- {
- //直接解析
- object? value = CallSiteRuntimeResolver.Instance.Resolve(callSite, Root);
- }
- return _engine.RealizeService(callSite);
- }
- }
复制代码 这段代码跟 CallSite 有关的一共有三个地方,分别是 GetCallSite 和 Resolve(callSite,Root)以及 _engine.RealizeService。其中 GetCallSite 是用来生成 CallSite 的(也就是上一节的主要内容),而剩下的两个则是对于 CallSite 的使用,也是这一节的主要内容。
RealizeService
我们先看一下 _engine.RealizeService 方法。- public override Func<ServiceProviderEngineScope, object?> RealizeService(ServiceCallSite callSite)
- {
- return scope =>
- {
- var result = CallSiteRuntimeResolver.Instance.Resolve(callSite, scope);
- return result;
- };
- }
复制代码 我们可以发现最终调用的还是 CallSiteRuntimeResolver.Instance.Resolve 这个方法,所以其实归根结底对 CallSite 的调用其实最终就是一个地方,也就是这个 Resolve 方法。
CallSiteRuntimeResolver.Resolve
- public object? Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
- {
- // 如果在 root scope 范围里已经有缓存了,直接返回
- if (scope.IsRootScope && callSite.Value is object cached)
- {
- return cached;
- }
- //调用 VisitCallSite 进行解析
- return VisitCallSite(callSite, new RuntimeResolverContext
- {
- Scope = scope
- });
- }
复制代码 VisitCallSite
- 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();
- }
- }
复制代码 VisitCallSite 会根据 Location 进行分支处理,Location 是 CallSite 里的一个属性。其中 Root 对应 Singleton,Scope 对应 Scope 生命周期,Dispose 对应 Trasient,None可以先将其理解为Singleton。
VisitRootCache(Single)
- protected override object? VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
- {
- // Singleton 懒加载 如果有 value 直接返回
- if (callSite.Value is object value)
- {
- // Value already calculated, return it directly
- return value;
- }
- var lockType = RuntimeResolverLock.Root;
- //在 root 范围进行解析
- ServiceProviderEngineScope serviceProviderEngine = context.Scope.RootProvider.Root;
- // 锁住 callSite 防止重复生成value
- lock (callSite)
- {
- // Lock the callsite and check if another thread already cached the value
- // 可能其他地方已经生成了,在获取一下看看
- if (callSite.Value is object callSiteValue)
- {
- return callSiteValue;
- }
- //最终依旧是调用了 VisitCallSiteMain 方法
- object? resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
- {
- Scope = serviceProviderEngine,
- AcquiredLocks = context.AcquiredLocks | lockType
- });
- serviceProviderEngine.CaptureDisposable(resolved);
- //进行缓存
- callSite.Value = resolved;
- return resolved;
- }
- }
复制代码 VisitScopeCache(Scope)
- // Check if we are in the situation where scoped service was promoted to singleton
- // and we need to lock the root
- // Scope 依赖 Singleton
- return context.Scope.IsRootScope ?
- VisitRootCache(callSite, context) :
- VisitCache(callSite, context, context.Scope, RuntimeResolverLock.Scope);
复制代码- private object? VisitCache(
- ServiceCallSite callSite,
- RuntimeResolverContext context,
- ServiceProviderEngineScope serviceProviderEngine,
- RuntimeResolverLock lockType)
- {
- bool lockTaken = false;
- object sync = serviceProviderEngine.Sync;
- // Dictionary<ServiceCacheKey, object?> ResolvedServices { get; } 缓存
- Dictionary<ServiceCacheKey, object?> resolvedServices = serviceProviderEngine.ResolvedServices;
- // Taking locks only once allows us to fork resolution process
- // on another thread without causing the deadlock because we
- // always know that we are going to wait the other thread to finish before
- // releasing the lock
- // 锁住 sync 对象
- if ((context.AcquiredLocks & lockType) == 0)
- {
- Monitor.Enter(sync, ref lockTaken);
- }
- try
- {
- //获取锁之后
- // Note: This method has already taken lock by the caller for resolution and access synchronization.
- // For scoped: takes a dictionary as both a resolution lock and a dictionary access lock.
- //先访问缓存
- 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;
- }
- finally
- {
- //解锁
- if (lockTaken)
- {
- Monitor.Exit(sync);
- }
- }
- }
复制代码 VisitDisposeCache(Transient)
- protected override object? VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
- {
- //解析
- var instance=VisitCallSiteMain(transientCallSite, context);
- return context.Scope.CaptureDisposable(instance);
- }
复制代码 VisitNoCache(None)
- protected virtual TResult VisitNoCache(ServiceCallSite callSite, TArgument argument)
- {
- return VisitCallSiteMain(callSite, argument);
- }
复制代码 VisitCallSiteMain
观察以上方法,我们可以发现无论是 VisitRootCache还是VisitScopeCache 等等,最终都是调用 VisitCallSiteMain 这个方法来生成的实例。- protected virtual TResult VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
- {
- //callSite.kind 是只读属性 ,在 GetCallSite 时确定,根据 CallSite 类型确定(例 ConstantCallSite)
- 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()));
- }
- }
复制代码 VisitConstructor
其中比较复杂的就是这个 VisitConstructor 方法,通过反射来构造实例,主要思路是拿到实例类型的构造函数,然后通过递归(调用VisitCallSite(见本文最上方))准备构造函数所需要的参数,最后调用 invoke 来生成实例。- protected override object VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
- {
- 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++)
- {
- //递归解析 VisitCallSite 见上文
- parameterValues[index] = VisitCallSite(constructorCallSite.ParameterCallSites[index], context);
- }
- }
- #if NETFRAMEWORK || NETSTANDARD2_0
- try
- {
- return constructorCallSite.ConstructorInfo.Invoke(parameterValues);
- }
- catch (Exception ex) when (ex.InnerException != null)
- {
- ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
- // The above line will always throw, but the compiler requires we throw explicitly.
- throw;
- }
- #else
- return constructorCallSite.ConstructorInfo.Invoke(BindingFlags.DoNotWrapExceptions, binder: null,
- parameters: parameterValues, culture: null);
- #endif
- }
复制代码 VisitFactory
- protected override object VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
- {
- //调用 Factory(Func<IServiceProvider, object> Factory) 委托(委托由开发者实现)
- return factoryCallSite.Factory(context.Scope);
- }
复制代码 VisitIEnumerable
- protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
- {
- //创建枚举类型的数组
- 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;
- }
复制代码 VisitConstant
- protected override object? VisitConstant(ConstantCallSite constantCallSite, RuntimeResolverContext context)
- {
- //直接返回保存的实例
- return constantCallSite.DefaultValue;
- }
复制代码 VisitServiceProvider
- protected override object VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, RuntimeResolverContext context)
- {
- return context.Scope;
- }
复制代码 总结
先根据实例的生命周期进行分支判断,接下来根据服务的生成方式进行分支判断。
来源:https://www.cnblogs.com/ccwzl/archive/2023/07/24/17512617.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|