我有一个使用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
。我本来希望的是工厂认识到没有组件而只是返回一个空值。
答案 0 :(得分:0)
史蒂文指出了两种探索方法来解决问题:
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...
}