Question

I'm using CQRS based on this Link and using SimpleInjector to fire up my Decorators. But they aren't getting fired. Am I doing something wrong here?

Here's my ICommandHandler part:

public interface ICommandHandler<TCommand> where TCommand : Command
{
    void Handle(TCommand command);
}

public interface ICommandHandler<TCommand, TResult> : ICommandHandler<TCommand> 
    where TCommand : Command<TResult>
{
}

And BaseCommandHandler part:

public abstract class BaseCommandHandler<TCommand> 
    : ICommandHandler<TCommand> where TCommand : Command
{
    public DbEntities Db { get; set; }

    public BaseCommandHandler(DbEntities db)
    {
        Db = db;
    }

    public BaseCommandHandler() : this(new DbEntities())
    {            
    }

    public abstract void Handle(TCommand command);
}

public abstract class BaseCommandHandler<TCommand, TResult> 
    : BaseCommandHandler<TCommand>
    where TCommand : Command<TResult>
{     
}

SimpleInjector Configuration:

container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
    typeof(BaseCommandHandler<>).Assembly);
container.RegisterDecorator(typeof(ICommandHandler<>),
    typeof(LoggerCommandHandlerDecorator<Command>));
container.RegisterDecorator(typeof(ICommandHandler<>),
    typeof(ValidationCommandHandlerDecorator<Command>));

Note: Both ICommandHandler and BaseCommandHandler reside in different library assemblies. This is done purposefully.

Any help will be appreciated!

Was it helpful?

Solution

You registered two closed-generic decorators, instead of the open-generic types. This is your registration:

container.RegisterDecorator(typeof(ICommandHandler<>),
    typeof(LoggerCommandHandlerDecorator<Command>));

What this configuration says is, for every ICommandHandler<T> implementation that is resolved, try to wrap it with an LoggerCommandHandlerDecorator<Command> when possible. Since you supplied the closed LoggerCommandHandlerDecorator<Command> however, it can only be applied to an ICommandHandler<Command> implementation, but never to any subtype of command such as with ICommandHandler<MoveCustomerCommand>.

The reason this is not possible, is because when someone requests an ICommandHandler<MoveCustomerCommand>, it expects an implementation of this type, but LoggerCommandHandlerDecorator<Command> does not implement ICommandHandler<MoveCustomerCommand>; it only implements ICommandHandler<Command>. So although a LoggerCommandHandlerDecorator<Command> could wrap an ICommandHandler<MoveCustomerCommand>, it can't be returned. It would cause an InvalidCastException.

So this should have been your registration:

container.RegisterDecorator(typeof(ICommandHandler<>),
    typeof(LoggerCommandHandlerDecorator<>));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top