我的大多数组件都是使用基于代码(流畅)的方法注册的,但是我需要在运行时以不同的方式解析一个特定的组件。这是界面和几个具体的实现: -
public interface ICommsService ...
public class SerialCommsService : ICommsService ...
public class TcpCommsService : ICommsService ...
我们的一些用户需要串行服务,而其他用户则需要TCP服务。我当前的解决方案(btw工作)是使用类型工厂和自定义组件选择器 - 后者读取app.config设置以确定键入的工厂将解析和返回的实现。
首先是打字的工厂(没什么特别的): -
public interface ICommsServiceFactory
{
ICommsService Create();
void Release(ICommsService component);
}
接下来,自定义组件选择器,从app.config读取完全限定的类型名称(例如“MyApp.SomeNamespace.TcpCommsService”): -
public class CommsFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return ConfigurationManager.AppSettings["commsServiceType"];
}
}
然后注册的东西: -
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ITypedFactoryComponentSelector>()
.ImplementedBy<CommsFactoryComponentSelector>());
container.Register(Component.For<ICommsFactory>()
.AsFactory(o => o.SelectedWith<CommsFactoryComponentSelector>()));
container.Register(Component.For<ICommsService>()
.ImplementedBy<SerialCommsService>().LifeStyle.Singleton);
container.Register(Component.For<ICommsService>()
.ImplementedBy<TcpCommsService>().LifeStyle.Singleton);
最后,一个依赖于ICommsService的示例类: -
public class Test
{
public Test(ICommsFactory commsFactory)
{
var commsService = commsFactory.Create();
...
}
}
正如已经提到的,上面的解决方案 工作,但我不喜欢注入工厂。如果我可以注入一个ICommsService
并让某个地方找出要解决和注入的实现,那就更直观了 - 类似于我现在正在做的事情,但早些时候在Windsor的“解决管道”中。有可能吗?
答案 0 :(得分:2)
您可以在此处使用UsingFactoryMethod
:
container.Register(Component.For<ICommsService>().UsingFactoryMethod(kernel => kernel.Resolve<ICommsServiceFactory>().Create()));
您现在可以将ICommsService
注入任何课程。 ICommsServiceFactory
现在可以是一个简单的界面:
interface ICommsServiceFactory
{
ICommsService Create();
}