Wine decorator

I'm trying to get a generic decorator around several non-generic handler commands. Is this possible without registering each handler separately?

Current Windsor command handler registration (working):

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

      

Simple decorator:

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

      

Simple command / handler:

public class MyCommand : IDomainCommand
{

}

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

      

I tried the following registration but the decorator is not being applied.

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

      

Suggestions?

EDIT: Another limitation that I forgot to mention initially is that some of these command handlers are used by two different applications. You need a decorator and not another.

+3


source to share


1 answer


You are probably getting "a dependency loop was encountered while trying to resolve a component ...", right? This is because the decorator ctor contains an IDomainCommandHandler <T>

public Decorator(IDomainCommandHandler<T> decoratedCommandHandler)

      

and when you try to resolve IDomainCommandHandler <T> inside Decorator it blows up.

The permission chain looks like this here:

  • Give me an IDomainCommandHandler

    //MyCommand type could be provided through a TypeFactoryComponentSelector     
    var myDecoratedCommandHandler = container.Resolve<IDomainCommandHandler<MyCommand>>();
    
          

  • The lock resolves Decorator <>, but then it resolves its own dependency

    IDomainCommandHandler<T> decoratedCommandHandler
    
          



And since you've already provided a T, which in this case is MyCommand, Castle goes to resolve the Decorator again, and when it does it twice it gives up. The only registration for IDomainCommandHandler is Decorator <T>. This issue is discussed here.

You can achieve "decorator" properties with DynamicProxy .

The decorator pattern is usually used when you want to extend an implementation. This is true? Can you give an example of a possible addition to your DomainCommandHandlers? Are you trying to implement Cross Cutting Concerns?

The only possible answer that sticks to your style is implementing a typed Factory object using ITypedFactoryComponentSelector or FactoryMethod and using a resolution stack. Then you can recursively traverse the container permission permission stack and return MyDomainCommandler if you have a Decorator on the stack. It is like a decision chain binding that says "Now I see that you are already resolving the Decorators dependencies, so please enable non Decorator again."

0


source







All Articles