I have two decorators:
class DbCommandWithTransactionHandlerDecorator<TCommand>
: IDbCommandHandler<TCommand> { ... }
class DbOptimisticConcurrencyRetryDecorator<TCommand>
: IDbCommandHandler<TCommand> { ... }
These decorators add transaction management and optimistic-concurrency retry capability to a database command.
I am using Autofac as my IoC container. I would like to setup Autofac such that it will auto-wire all IDbCommandHandler<> found in an assembly, such that when I request say an IDbCommandHandler<CreateNewNotificationCommand>, it will automatically decorate it with first a DbCommandWithTransactionHandlerDecorator, and then a DbOptimisticConcurrencyRetryDecorator.
I’ve been trying to get this with Autofac’s builder.RegisterGenericDecorator(), but haven’t yet managed. The main issue is that a decorator requires a ‘named’ argument to work. Below is the sample code that is most ‘near’ to what I want to achieve – However the main flaw is that I still had to manually register the types.
var builder = new ContainerBuilder();
var a = Assembly.GetExecutingAssembly();
// I need to find a way how these can be 'auto-wired',
// rather than having to manually wire each command.
builder.RegisterType<CreateNewNotificationCommandHandler>()
.Named<IDbCommandHandler<CreateNewNotificationCommand>>("command");
builder.RegisterType<CreateNewNotificationCommandHandler_2>()
.Named<IDbCommandHandler<CreateNewNotificationCommand_2>>("command");
builder.RegisterGenericDecorator(
typeof(DbCommandWithTransactionHandlerDecorator<>),
typeof(IDbCommandHandler<>),
fromKey: "command");
var container = builder.Build();
var handler1 =
container.Resolve<IDbCommandHandler<CreateNewNotificationCommand>>();
var handler2 =
container.Resolve<IDbCommandHandler<CreateNewNotificationCommand_2>>();
handler1.Handle(null); //these are correctly decorated
handler2.Handle(null); //these are correctly decorated
I did manage to find a workaround via reflection, which although it works is not really elegant. I will post it below for completeness sake:
First, I get via reflection all the types that implement
IDbCommandHandler. Then, I register them as named types for all the interfaces which they implement, giving them a name of ‘dbCommand’.Then, I register the generic decorator to decorate types named ‘dbCommand’. This decorater is named ‘dbCommandWithTransaction’, and is used to then register another generic decorator for the concurrency-retry.
Considering this is something which would be done once and ‘forgotten’, I was ready go with this workaround. However, I was trying out other IoC containers and came upon Simple Injector, and all this can be done in just two lines of code – And have since then won me over.