Castle.Windsor:来自类型工厂的组件的可选解析

时间:2014-04-08 14:32:58

标签: wcf dependency-injection castle-windsor

我有一个使用Castle.Windsor的WCF服务设置;消息到达调度程序,将调度程序发送到正确的组件(基本上是IHandler<Message>,消息是查询)。

但是在某些情况下,在处理程序可以执行之前还有一个额外的操作;必须使用来自其他地方的数据来完成消息。我想要的是检查我的消息类型是否存在注入器,如果存在,则运行它。

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");
}

这背后的原因是,在未来的某个时候,有人可能会创建一个IInjector<Message>的插件,我想在将来的时间选择它;但目前它不存在。

当找不到组件而不是抛出ComponentNotFoundException时,是否可以让类型工厂返回null?

修改

正如@Steven所讨论的那样,我将回答我自己的问题,以便编译导致我找到解决方案和解决方案的原因。首先让我们重申一下问题

我的WCF服务基本上遵循KrzysztofKoźmic在this article

中描述的结构

但是,在调用处理程序之前,我希望有一个optionnal操作,如果需要,可以修改传入消息。

private static void DoActualWork<T>(T command)
{
    IInjector<T> Injector = injectorFactory.GetInjector<T>();
    if (Injector != null) { Injector.InjectThings(command, ""); }
    var handlers = factory.GetHandlersForCommand(command);
    foreach (var handler in handlers)
    {
        handler.Execute();
    }
}

我在使用injectorFactory时遇到了问题;当我要求它找到一个不存在的组件时,它会抛出一个ComponentNotFoundException。我本来希望的是工厂认识到没有组件而只是返回一个空值。

1 个答案:

答案 0 :(得分:0)

史蒂文指出了两种探索方法来解决问题:

  • 请勿检查是否为空,而是使用Null Object Pattern
  • 用装饰器包裹IHandler<T>并在装饰器中注入IInjector

第二种选择是不可取的,因为它会给处理者带来他们不必了解的责任。理想情况下,我应该将这种注入行为移动到它自己的独立拦截器中,让它完全存在,而不需要任何其他代码知道它。我可以稍后再这样做。

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

不要尝试根据基础对象创建一个注入器:

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());

现在,如果Castle.Windsor可以解析特定的IInjector<Command>,那么它将返回NopInjector。不再空检查:

private static void DoActualWork<T>(T command)
{
    injectorFactory.GetInjector<T>().InjectThings(command, "");
    // calling handlers...
}