ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Net6 DI源码分析Part3 CallSiteRuntimeResolver,CallSiteVisitor

2022-02-09 11:31:08  阅读:202  来源: 互联网

标签:resolved return CallSiteVisitor DI argument callSite 源码 context VisitCallSiteMai


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

标签:resolved,return,CallSiteVisitor,DI,argument,callSite,源码,context,VisitCallSiteMai
来源: https://www.cnblogs.com/hts92/p/15812761.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有