使用Castle Windsor注入Lazy的收集

时间:2017-05-10 15:40:14

标签: dependency-injection castle-windsor

我创建了这个界面:

public interface IGate
{
  string Name { get; }
  void Send();
}

在运行时我需要从这个接口的多个实现中选择一个与我相关的实现(根据我将在WCF请求中获取的数据)。

因为我在这个项目中使用Castle Windsor作为我的DI容器 我做了类似的事情:

    public class GateFactory : IGateFactory
    {
       private IList<IGate> _list;
       public GateFactory(IList<IGate> listOfGates)
       {
          _list = listOfGates;
       }

       public IGate Create(string name)
       {
          return _list.First(o => o.Name == name);
       }
    }

所以在我的代码中我使用IGateFactory来创建适当的IGate(再次根据我将在运行时使用的名称)。

我用container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));解析了这个集合 在我的配置代码中

问题是我不想在系统中实例化所有盖茨,因为我知道我只会使用其中一个(我会有30个盖茨之类的东西)。

我想注入IList<Lazy<IGate>>但是当我在列表上运行以检查每个人的名字时,我将实际上实例化每一个人,这正是我想要避免的。

另一种解决方案是注入像IDictionary<string,Lazy<IGate>>这样的东西,但我不知道如何配置它 (使用代码)

还要注意我每次获得GateFactory时都需要新的集合(可能是列表或字典)(LifeStyle.Transient)

1 个答案:

答案 0 :(得分:0)

您需要的是Typed Component Selector。为什么这个?因为你的陈述

  

在运行时我需要从这个界面的多个实现中选择与我相关的那个

问题应该是&#34;如何根据参数在运行时选择多个实现?&#34;

当您必须从已经实现的实现中进行选择时 - 转到组件选择器(从组件选择器工厂模式的意义上读取它而不是实现的名称) - 在运行时选择正确组件的人。

当你必须在运行时用 params 创建一些东西时,比如连接或在调用之前不存在的其他东西 - 去工厂方法或创建 new的其他东西运行时的东西。

您的案件excerpt

public class CustomTypedFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
    protected override string GetComponentName(MethodInfo method, object[] arguments)
    {
        if (method.Name == "GetById" && arguments.Length == 1 && arguments[0] is string)
        {
            return (string)arguments[0];
        }
        return base.GetComponentName(method, arguments);
    }
}

// somewhere in your registration ....
var ioc = new WindsorContainer();
ioc.AddFacility<TypedFactoryFacility>();
ioc.Register(Component.For<ITypedFactoryComponentSelector>().ImplementedBy<CustomTypedFactoryComponentSelector>());

here开始阅读。

对于 Lazy 部分 - 它将被选中并实例化运行时。将组件注册为瞬态,以便每次都有新的实现。通过这样做你会尽可能地变得懒惰,因为实例将在最后可能的时刻创建,并将按照您的喜好处理。

这是how castle windsor tracks components的解释。