Question

How to register a conditional decorator in SimpleInjector? Here are my definitions:

public interface ICommand { }

public interface ICleanableCommand : ICommand {
    void Clean();
}

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

public class CleanableCommandHandlerDecorator<TCommand> 
    : ICommandHandler<TCommand> 
    where TCommand : ICleanableCommand {

    private readonly ICommandHandler<TCommand> _handler;

    public CleanableCommandHandlerDecorator(
        ICommandHandler<TCommand> handler) {
        _handler = handler;
    }

    void ICommandHandler<TCommand>.Handle(TCommand command) {
        command.Clean();
        _handler.Handle(command);
    }
}

And I'm trying:

container.RegisterManyForOpenGeneric(
    typeof(ICommandHandler<>),
    AppDomain.CurrentDomain.GetAssemblies()
    );

container.RegisterDecorator(
    typeof(ICommandHandler<>),
    typeof(CleanableCommandHandlerDecorator<>)
    // ,context => context.ImplementationType ???
    // I want to register this decorator for commandhandlers 
    // which their command implements ICleanableCommand 
    );
Was it helpful?

Solution

You can use the RegisterDecorator overload that takes an DecoratorPredicateContext to define the condition under which your decorator should be applied. However, since in your case the condition is just the generic type constraint, you don't have to supply a predicate. Simple Injector will automatically ignore the decorator when the given service type is not decoratable, and this includes generic type constraints.

In other words, just register your decorator as follows and it will work correctly:

container.RegisterDecorator(
    typeof(ICommandHandler<>),
    typeof(CleanableCommandHandlerDecorator<>));

OTHER TIPS

It seems I can use DecoratorPredicateContext.ServiceType:

container.RegisterDecorator(
    typeof(ICommandHandler<>),
    typeof(CleanableCommandHandlerDecorator<>),
    context => {
        var genArg = context.ServiceType.GetGenericArguments()[0];
        return typeof(ICleanableCommand).IsAssignableFrom(genArg);
    });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top