注入Castle Windsor类型工厂的其他选择?

时间:2015-02-19 11:37:55

标签: castle-windsor

我的大多数组件都是使用基于代码(流畅)的方法注册的,但是我需要在运行时以不同的方式解析一个特定的组件。这是界面和几个具体的实现: -

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的“解决管道”中。有可能吗?

1 个答案:

答案 0 :(得分:2)

您可以在此处使用UsingFactoryMethod

container.Register(Component.For<ICommsService>().UsingFactoryMethod(kernel => kernel.Resolve<ICommsServiceFactory>().Create()));

您现在可以将ICommsService注入任何课程。 ICommsServiceFactory现在可以是一个简单的界面:

interface ICommsServiceFactory
{
    ICommsService Create(); 
}