Net6DI源码分析Part3CallSiteRuntimeResolver,CallSiteVisitor

博客 分享
0 269
张三
张三 2022-02-11 10:55:12
悬赏:0 积分 收藏

Net6 DI源码分析Part3 CallSiteRuntimeResolver,CallSiteVisitor

CallSiteRuntimeResolver

CallSiteRuntimeResolver是实现了CallSiteVisitor之一。
提供的方法主要分三个部分

  1. 自有成员方法

    1. Resolve提供服务
    2. VisitCache
    3. 私有构造函数
  2. 重写父类方法

    1. VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
      调用父类VisitCallSiteMain ,并把创建出来的服务添加到context.Scope.CaptureDisposable

      return context.Scope.CaptureDisposable(VisitCallSiteMain(transientCallSite, context));
    2. object VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)

      1. 先找对应callSite.Value是否有值如果有直接返回
      2. 如果没有直接调用 VisitCallSiteMain创建服务并把对象rootServiceProviderEngine内。
      3. 创建的服务放入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;
    3. VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)

      1. 先去serviceProviderEngine.resolvedServices拿,有的话直接返回如果没拿到执行步骤2去创建。serviceProviderEngine.resolvedServices.TryGetValue(callSite.Cache.Key, out object resolved)
      2. VisitCallSiteMain创建对象
      3. 把创建后的对象加入对应Scope的 disposable列表
      4. 把创建后的对象加入对应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;
  3. 实现父类抽象方法

    1. VisitConstructor
      1. 给构造方法提供参数(如果有参数递归调用VisitCallSite创建参数对象)
      2. 直接调用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);
    2. override object VisitConstant(ConstantCallSite constantCallSite, RuntimeResolverContext context)
      直接返回CallSite对象的DefaultValue
      return constantCallSite.DefaultValue;
    3. VisitServiceProvider
      return context.Scope;
    4. 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;
    5. VisitFactory
      return factoryCallSite.Factory(context.Scope);

体力活都给CallSiteFactory了

CallSiteVisitor
  1. 方法
    1. VisitCallSite(ServiceCallSite callSite, TArgument argument)

      1. 保证Stack安全
      2. 根据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(); }
    2. VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)

      1. 根据不同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()));  }
  2. 虚方法
    1. TResult VisitNoCache(ServiceCallSite callSite, TArgument argument) => VisitCallSiteMain(callSite, argument);
    2. TResult VisitDisposeCache(ServiceCallSite callSite, TArgument argument) -> isitCallSiteMain(callSite, argument);
    3. TResult VisitRootCache(ServiceCallSite callSite, TArgument argument) -> VisitCallSiteMain(callSite, argument);
    4. TResult VisitScopeCache(ServiceCallSite callSite, TArgument argument) => VisitCallSiteMain(callSite, argument);

    根据生命周期策略由子类实现对应存储机制。

  3. 抽象方法
    1. TResult VisitConstructor(ConstructorCallSite constructorCallSite, TArgument argument);
    2. TResult VisitConstant(ConstantCallSite constantCallSite, TArgument argument);
    3. TResult VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, TArgument argument);
    4. TResult VisitIEnumerable(IEnumerableCallSite enumerableCallSite, TArgument argument);
    5. TResult VisitFactory(FactoryCallSite factoryCallSite, TArgument argument);

    根据服务注册时的创建机制策略由子类实现对应的创建对象机制。

CallSiteVisitor负责这活怎么干!。CallSiteRuntimeResolver负责干活

  1. 调用 VisitCallSite在内部区分出scope并调用具体实现方法缓存方法 (CallSiteResultCacheLocation),
    -> VisitCache方法
    -> 但是在缓存前得先得到被缓存的对象,这时通过调用(VisitCallSiteMain)创建对象
    -> VisitCallSiteMain根据提供的callsite类型去调用实现的抽象方法创建对应对象
    -> 根据cache对应的方法缓存步骤1.1的结果。
  2. 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

文章中提到的代码,请在source.dot.net快速搜索预览


本文来自博客园,作者:一身大膘,转载请注明原文链接:https://www.cnblogs.com/hts92/p/15812761.html

posted @ 2022-02-11 10:51 一身大膘 阅读(10) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员