The problem is that Simple Injector will never be able to wrap an ICommandHandler<T>
implementation with one of your decorators, because there is an unresolvable generic type TCommand
. You would have noticed this if the Handle
method of your decorators would call the decorated
instance. For instance:
public class CreateValidFriendlyUrlCommandHandler<TCommand>
: ICommandHandler<CreateProductCommand>
{
private readonly ICommandHandler<TCommand> decorated;
public CreateValidFriendlyUrlCommandHandler(
ICommandHandler<TCommand> decorated)
{
this.decorated = decorated;
}
public void Handle(CreateProductCommand command)
{
// This won't compile since CreateProductCommand and
// TCommand are not related.
this.decorated.Handle(command);
}
}
This code won't compile, since the decorator's Handle
method takes an CreateProductCommand
argument, while the decorated
instance takes a TCommand
argument, which isn't specified (and nowhere is stated that CreateProductCommand
is a TCommand
).
In fact you didn't create a decorator at all. A decorator wraps an instance of the same interface that it implements. You wrap an ICommandHandler<TCommand>
while you implement an ICommandHandler<CreateProductCommand>
. The only way you would get this to work is when you explicitly specify the TCommand
to be a CreateProductCommand
, as follows:
ICommandHandler<CreateProductCommand> handler =
new CreateValidFriendlyUrlCommandHandler<CreateProductCommand>(
new CreateProductCommandHandler()
);
Still, there is no way for Simple Injector to 'guess' that this TCommand
should be a CreateProductCommand
and that's why your 'decorator' didn't get wrapped.
Long story short: ditch the TCommand
:
public class CreateValidFriendlyUrlCommandHandler
: ICommandHandler<CreateProductCommand>
{
private ICommandHandler<CreateProductCommand> decorated;
public CreateValidFriendlyUrlCommandHandler(
ICommandHandler<CreateProductCommand> decorated)
{
this.decorated = decorated;
}
public void Handle(CreateProductCommand command)
{
// logic here
}
}
Or make it generic with a type constraint:
public class CreateValidFriendlyUrlCommandHandler<TCommand>
: ICommandHandler<TCommand>
where TCommand : CreateProductCommand
{
private ICommandHandler<TCommand> decorated;
public CreateValidFriendlyUrlCommandHandler(
ICommandHandler<TCommand> decorated)
{
this.decorated = decorated;
}
public void Handle(TCommand command)
{
// logic here
}
}
or remove the type constraint and allow handling any type of command, not only CreateProductCommand
.
Note that if you are defining many decorators that can only handle one specific type of command handler, you might want to reconsider your strategy. There might be a problem in your design.