【问题标题】:How to resolve a type by name from the container at runtime using Autofac?如何使用 Autofac 在运行时从容器中按名称解析类型?
【发布时间】:2014-10-20 23:29:48
【问题描述】:

我试图弄清楚如何使用 Autofac 3.5.2 在运行时从容器中按名称解析类型。我的用例是每个业务伙伴都有一个自定义回调策略,需要容器注入不同的类型,但是直到运行时我才知道我需要哪种伙伴策略。所以:

class PartnerAStrategy(ISomeType aSomeType, ILog someLog) : ICallbackStrategy {}

class PartnerBStrategy(ISomeOtherType aSomethingElse, IShoe aSneaker) : ICallbackStrategy {}

我知道在使用它的类已经解决之后我需要哪种策略

class PartnerSSOController {
    void PartnerSSOController(IPartnerFactory aFactory){ 
        thePartnerFactory = aFactory;
    }

    void DoLogin(){
        // 'PartnerB'
        string aPartner = GetPartnerNameFromContext();
        //get from container, not reflection
        ICallbackStratgey aStrategy = thePartnerFactory.ResolveCallback(aPartner);
        aStratgey.Execute();
    }
}

class PartnerFactory : IPartnerFactory{
    ICallbackStratgey ResolveCallback(string aPartnerName){
        string aCallbackTypeINeed = string.format("SSO.Strategies.{0}Strategy", aPartnerName);
        // need container to resolve here
    }
}

假设一切都已成功注册到容器中,我将如何在我的 Autofac SSO 模块中注册回调?我试过这个:

aBuilder.Register(aComponentContext => {
                      IPartnerFactory aFactory = aComponentContext.Resolve<IPartnerFactory>();
                      string aTypeName = String.Format("SSO.Strategies.{0}Strategy", /** how to access partner name here? **/);
                      Type aTypeToReturn = Type.GetType(aTypeName, false, true) ?? typeof(DefaultCallbackStrategy);
                      return aComponentContext.Resolve(aTypeToReturn);
                  })
        .As<ICallbackStrategy>()

但如您所见,我不知道如何在回调期间使合作伙伴或类型名称可用。 我宁愿避免专门注册每个合作伙伴的回调并尽可能提供键名,因为我喜欢扫描程序集以查找我模块中的类型:

 aBuilder.RegisterAssemblyTypes(typeof(CallbackBase).Assembly)
    .Where(aType => typeof(ICallbackStrategy).IsAssignableFrom(aType))
    .AsImplementedInterfaces()
    .AsSelf();

【问题讨论】:

    标签: dependency-injection autofac


    【解决方案1】:

    我认为您正在寻找的是 Autofac 元数据支持,特别是您可以在程序集扫描中使用的属性元数据。这里有大量文档和示例:http://autofac.readthedocs.org/en/latest/advanced/metadata.html

    【讨论】:

      【解决方案2】:

      我认为 Travis 使用 MetaData 的方法可能奏效了,但这是我今天解决这个问题的方法。

      我的真实场景使用SSOPartner 对象,而不是我在原始问题中使用的字符串PartnerName,因此请注意这一点。

      首先,我通过查找实现ICallbackStrategy 的每种类型,在 SSO 程序集中注册所有自定义合作伙伴策略。 CallbackBase 是目标程序集中的类型:

      aBuilder.RegisterAssemblyTypes(typeof(CallbackBase).Assembly)
              .Where(aType => typeof(ICallbackStrategy).IsAssignableFrom(aType))
              .AsImplementedInterfaces()
              .AsSelf();
      

      然后我在作文根注册了Func&lt;ISSOPartner, ICallbackStrategy&gt;

      aBuilder.Register<Func<ISSOPartner, ICallbackStrategy>>((aComponentContext, aPartner) => {
                                                                  IComponentContext aResolvedContext = aComponentContext.Resolve<IComponentContext>();
                                                                  return aSSOPartner => {
                                                                             string aType = String.Format("SSO.Strategies.{0}Strategy", aSSOPartner.Name);
                                                                             Type aCallbackType = Type.GetType(aType, false, true);
                                                                             return (ICallbackStrategy)aResolvedContext.Resolve(aCallbackType, new NamedParameter("anSSOPartner", aSSOPartner));
                                                                         };
                                                              });
      

      如您所见,每个策略都将构造函数中的SSOPartner 对象作为命名参数。这有助于演示如何使用混合类型从容器中解析对象,其中一些类型已在容器中注册,而另一些则没有。

      所以让我更新我原来的例子:

      class PartnerAStrategy(ISSOPartner anSSOPartner) : ICallbackStrategy {}
      

      class PartnerBStrategy(ISSOPartner anSSOPartner, IShoe aSneaker) : ICallbackStrategy {}
      

      aResolvedContext.Resolve 将在运行时通过查看容器找到 PartnerB 的 IShoe。容器不知道ISSOPartner

      最后,我在需要使用它的位置依赖Func&lt;ISSOPartner, ICallbackStrategy&gt;,并调用它来调用我在组合根中定义的lambda:

      public class SSOController : Controller {
          private readonly Func<ISSOPartner, ICallbackStrategy> theCallbackResolverFunc;
      
          public SSOController(Func<ISSOPartner, ICallbackStrategy> aCallbackResolverFunc){
              theCallbackResolverFunc=aCallbackResolverFunc;
          }
      
          public async Task<ActionResult> DoSSO() {
              SSOPartner anSSOPartner = GetThePartner();
              ICallbackStrategy aCallback = theCallbackResolverFunc.Invoke(anSSOPartner);
              var aReturn = await aCallback.Execute();
              ...
          }
      }
      

      SSOController 传递了对我在组合根中注册的Func 的引用。我执行该 Func 并传入SSOPartner,它有一个名为Name 的属性,我用它来解析ICallbackStrategy 类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-28
        • 1970-01-01
        • 2018-08-31
        • 1970-01-01
        • 2014-01-17
        • 1970-01-01
        相关资源
        最近更新 更多