我创建了这个界面:
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)
答案 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 部分 - 它将被选中并实例化运行时。将组件注册为瞬态,以便每次都有新的实现。通过这样做你会尽可能地变得懒惰,因为实例将在最后可能的时刻创建,并将按照您的喜好处理。