Castle.Windsor:来自一个类型工厂的组件的可选分辨率 [英] Castle.Windsor: optional resolution of component from a typed factory

查看:266
本文介绍了Castle.Windsor:来自一个类型工厂的组件的可选分辨率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

  IInjector< ;消息> Injector = InjectorFactory.RetrieveInjector< Message>(); 
if(Injector!= null)
{
Logger.InfoFormat(IInjector< {0}&OK),input.GetType()。Name);
Injector.InjectCode(输入,数据来自其他地方);
}

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



当没有找到一个组件而不是抛出一个 ComponentNotFoundException ?



编辑



与@Steven我会回答我自己的问题,以编译什么导致我的解决方案和我发现的决议。首先让我们重述一下这个问题。

我有一个WCF服务基本上遵循KrzysztofKoźmic在这篇文章



但是,在调用处理程序之前,我希望有一个选项操作,如果需要,传入的消息将被修改。

  private static void DoActualWork< T>(T命令)
{
IInjector< T>注射器=注射器工件。注射器T();
if(Injector!= null){Injector.InjectThings(command,); }
var handlers = factory.GetHandlersForCommand(command);
foreach(处理程序中的var handler)
{
handler.Execute();
}
}

我与injectFactory有问题;当我要求它找到一个不存在的组件时,它会抛出一个 ComponentNotFoundException 。我想要的是工厂认识到没有组件,只是返回null。

解决方案

史蒂文指出两个探索解决方案的方法:




  • 不要检查null,而是使用空对象模式

  • 包含 IHandler< T> 与装饰器,并在装饰器中注入IInjector



第二个选项是不可取的,因为它将加载处理程序他们不必了解的责任。理想情况下,我应该将这种注入行为转移到自己的独立拦截器中,让它完全在那里生存,而不需要任何其他代码知道它。我可以稍后这样做。



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



strong>不要尝试根据基础对象创建注射器:

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

相反,创建一个通用注入器并将其注册为一个打开的通用组件

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

//注册
_container.Register(
组件.For(typeof(IInjector?))
.ImplementedBy(typeof(NopInjector?))
.IsDefault());
_container.Register(
Classes
.FromAssemblyInThisApplication()
.BasedOn(typeof(IInjector?))
.WithService.AllInterfaces());

现在,如果Castle.Windsor可以解析特定的 IInjector< Command> code>它会,否则它会返回 NopInjector 。没有更多的空检查:

  private static void DoActualWork< T>(T命令)
{
injectFactory .GetInjector< T>()。InjectThings(command,);
//调用处理程序...
}


I have a WCF service setup with Castle.Windsor; messages arrive to a dispatcher that send them to the right component (basically a IHandler<Message> with message being a query).

However in some cases there is one additional before the handler can act; the message must be completed with data coming from someplace else. What i want is to check whether there exists an injector for the type of my message and if one exists, run it.

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

The reasoning behind this is that at some future point somebody may create a plugin with a IInjector<Message> and I want to pick it at a future time; but at the moment it doesn't exist.

Is it possible to have a typed factory returning null when a component is not found instead of throwing a ComponentNotFoundException?

EDIT

As discussed with @Steven I will be answering my own question in order to compile what lead me to the solution and the resolution i found. First let's restate the problem

I have a WCF service basically following the structure described by Krzysztof Koźmic in this article

However, before calling the handlers i wanted to have an optionnal operation where the incoming message would be modified if needed.

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

I was having a problem with the injectorFactory; when i asked it to find a non-existing component it would throw a ComponentNotFoundException. What i would have liked is for the factory to recognize there was no component and simply return a null.

解决方案

Steven points out two ways to explore to reach a solution :

  • Don't check for null, rather use a Null Object Pattern
  • Wrap the IHandler<T> with a decorator and inject the IInjector in the decorator

The second option was not desirable since it would have loaded the handlers with a responsibility they didn't have to know about. Ideally I should move this injection behavior into its own independent interceptor and let it live entirely there without any other code knowing about it. I may do that later.

The first point though is the way to go. Null Object Pattern decreases the complexity of my method and leaves it much clearer than with a null check. All i have to do is create a NopInjector class and declare it as the default value for the factory.

Don't try to create an injector depending on a base object:

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

Rather create a generic injector and register it as an open generic component

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

Now if Castle.Windsor can resolve a specific IInjector<Command> it will, else it will return the NopInjector. No more null check:

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

这篇关于Castle.Windsor:来自一个类型工厂的组件的可选分辨率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆