温莎通用装饰

时间:2014-10-15 16:08:06

标签: c# generics castle-windsor ioc-container

我正在尝试围绕几个非通用命令处理程序获取通用装饰器。如果不单独注册每个命令处理程序,这是否可行?

当前Windsor命令处理程序注册(有效):

container.Register(Classes.FromAssemblyNamed(namespaceName)
    .BasedOn(typeof(IDomainCommandHandler<>))
    .WithService.AllInterfaces()
    .LifestyleTransient());

简单的装饰者:

public class Decorator<T> : IDomainCommandHandler<T> where T : IDomainCommand
{
    private readonly IDomainCommandHandler<T> _decoratedCommandHandler;

    public Decorator(IDomainCommandHandler<T> decoratedCommandHandler)
    {
        _decoratedCommandHandler = decoratedCommandHandler;
    }

    public void Handle(T command)
    {
        _decoratedCommandHandler.Handle(command);
    }
}

简单的命令/处理程序:

public class MyCommand : IDomainCommand
{

}

public class MyCommandHandler : IDomainCommandHandler<MyCommand>
{
    public void Handle(MyCommand command)
    {
    }
}

我尝试了以下注册,但未应用装饰器。

container.Register(Component.For(typeof(IDomainCommandHandler<>))
    .ImplementedBy(typeof(Decorator<>))
    .LifestyleTransient());

建议?

编辑: 我最初忘记提到的另一个限制是这些命令处理程序中的一些由两个不同的应用程序使用。一个需要装饰者,另一个不需要。

1 个答案:

答案 0 :(得分:0)

可能你得到&#34;在尝试解析组件时已经检测到依赖性循环...&#34;,对吧?这是因为装饰器的ctor包含IDomainCommandHandler&lt; T&gt;

public Decorator(IDomainCommandHandler<T> decoratedCommandHandler)

当您尝试解析IDomainCommandHandler&lt; T&gt;时装饰者里面爆炸了。

此处的解决方案链如下:

  1. 给我IDomainCommandHandler

    //MyCommand type could be provided through a TypeFactoryComponentSelector     
    var myDecoratedCommandHandler = container.Resolve<IDomainCommandHandler<MyCommand>>();
    
  2. Castle解析了Decorator&lt;&gt;但后来它解决了自己的依赖

    IDomainCommandHandler<T> decoratedCommandHandler
    
  3. 因为你已经提供了T,在这种情况下是MyCommand,Castle再一次解决了Decorator,当它再做两次时 - 它放弃了。 IDomainCommandHandler的唯一注册是Decorator&lt; T&gt;。讨论了这类问题here

    你可以实现装饰&#34;喜欢DynamicProxy的属性。

    当您想要扩展实现时,通常会应用装饰器模式。是这样的吗?你能给出一个可能扩充你的DomainCommandHandlers的例子吗?您是否正在尝试实施Cross Cutting Concerns?

    唯一可能符合您风格的答案是使用ITypedFactoryComponentSelector或FactoryMethod实现Typed Factory Facility并使用分辨率堆栈。然后,您可以递归遍历容器的分辨率堆栈,如果堆栈中有Decorator,则返回MyDomainCommandler。这看起来像解决方案链的一个钩子,它说&#34;现在我看到你已经解决了装饰器的依赖关系,所以请不要再解析装饰器。&#34;