Wcf Windsor:来自类型化工厂的可选组件解析

Wcf Windsor:来自类型化工厂的可选组件解析,wcf,dependency-injection,castle-windsor,Wcf,Dependency Injection,Castle Windsor,我与Castle.Windsor建立了WCF服务;消息到达分派器,分派器将消息发送到正确的组件(基本上是IHandler),消息是一个查询 然而,在某些情况下,在处理程序可以采取行动之前还有一个额外的步骤;消息必须使用来自其他地方的数据完成。我要做的是检查是否存在针对我的消息类型的注入器,如果存在,请运行它 IInjector<Message> Injector = InjectorFactory.RetrieveInjector<Message>(); if (Inje

我与Castle.Windsor建立了WCF服务;消息到达分派器,分派器将消息发送到正确的组件(基本上是IHandler),消息是一个查询

然而,在某些情况下,在处理程序可以采取行动之前还有一个额外的步骤;消息必须使用来自其他地方的数据完成。我要做的是检查是否存在针对我的消息类型的注入器,如果存在,请运行它

IInjector<Message> Injector = InjectorFactory.RetrieveInjector<Message>();
if (Injector != null)
{
    Logger.InfoFormat("IInjector<{0}> OK", input.GetType().Name);
    Injector.InjectCode(input, "Data coming from somewhere else");
}

我在注射厂遇到了问题;当我要求它查找一个不存在的组件时,它会抛出一个ComponentNotFoundException。我希望工厂能够识别出没有组件,只返回空值。

Steven指出了两种探索解决方案的方法:

不要检查null,而是使用 用装饰器包裹IHandler,并将IInjector注入装饰器 第二种选择是不可取的,因为它会让处理者承担他们不必知道的责任。理想情况下,我应该将这种注入行为转移到它自己的独立拦截器中,并让它完全存在于其中,而不让任何其他代码知道它。我可能以后再做

第一点是要走的路。空对象模式降低了我的方法的复杂性,并使它比空检查更清晰。我所要做的就是创建一个NopInjector类,并将其声明为工厂的默认值

不要试图根据基础对象创建喷油器:

public class NopInjector : IInjector<object>
{
    public void InjectStuff(object target, string stuff) { }
}

您永远不应该返回null。而是返回一个“默认”或“空”实现,请参阅。这样你就永远不需要检查NULL了。你可能还想考虑用一个注入器注入一个装饰器来包装IHANDER。@史提芬:我没有考虑空对象模式;这是一个非常好的主意,但是如何在Castle.Windsor中配置它呢?我应该注册一个无类型的IInjector吗?我不是Castle专家,但您可以注册一个开放的泛型实现,如下所示:container.RegisterComponent.forTypeOfInjector.ImplementedBytypeofNullInjector;。但是,当为某个消息显式注册实现时,您必须尝试一下它是如何工作的。@Steven谢谢;如果你能把你的评论整理成一个答案,我会接受的。如果没有,我将自己编译它们以供参考
public class NopInjector : IInjector<object>
{
    public void InjectStuff(object target, string stuff) { }
}
public class NopInjector<T> : IInjector<T>
{
    public void InjectStuff(T target, string stuff) { }
}

// registration
_container.Register(
            Component.For(typeof(IInjector<>))
            .ImplementedBy(typeof(NopInjector<>))
            .IsDefault());
_container.Register(
            Classes
            .FromAssemblyInThisApplication()
            .BasedOn(typeof(IInjector<>))
            .WithService.AllInterfaces());
private static void DoActualWork<T>(T command)
{
    injectorFactory.GetInjector<T>().InjectThings(command, "");
    // calling handlers...
}