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