jonho jonho - 1 year ago 75
C# Question

Decorators decorating base Commands

I am using SimpleInjector

I have a MVC 4.0 project and am using the decorator pattern around my Commands to manage my UnitOfWork and my Authorisation.
I have decorator which does authorisation - the

. This wraps all of my
is also decorated by
.) The authorisation decorator looks like this:

public void Handle(TCommand command)
//authorise this command for this Iprincipal


I now want to create a
(that doesn’t need an NHibernate session, it just does some File IO).
Note both
inherit from
– which looks like so:

public interface ICommandHandler<in TCommand, out TResult>
TResult Result { get; }
void Handle(TCommand command);

I don’t really want to have to create two identical
(transactional/non transactional). Because ultimately they decorate a base
( which is implemented as either a

So my question is - Is there any way to create 1 Decorator that decorates a base
- but the container knows to cast up the
to a
or an
. Is there any way to do this?

Answer Source

If you register all command handlers by their ICommandHandler<TCommand, TResult> interface, you can't wrap part of the handlers with a decorator that wraps an ITransactionalCommandHandler<TCommand, TResult>. You can only apply such decorator if the handlers are explicitly registered by that ITransactionalCommandHandler<TCommand, TResult> interface, but this is not something you should do. You don't want that, since that means that the consumers of those commands need to know whether the handlers is transactional or not, which they shouldn't care about (it's a implementation detail).

Your transactional decorator should therefore wrap an ICommandHandler<TCommand, TResult>. If it needs access to the ITransactionalCommandHandler<TCommand, TResult> interface, the decorator should cast the input parameter from ICommandHandler to ITransactionalCommandHandler.

What you need is to register your decorators based on a predicate, as follows:

// NOTE: In Simple Injector v2.x use 'ManyForOpenGeneric' instead.
container.Register(typeof(ICommandHandler<,>), myAssemblies);

container.RegisterDecorator(typeof(ICommandHandler<,>), typeof(TransactionDecorator<,>), 
    c => typeof(ITransactionalCommandHandler<,>)

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

The predicate ensures that only command handlers are decorated that implement the ITransactionalCommandHandler<,>.

Instead of using that interface, you might also mark the handlers with an attribute:

class ShipOrderCommandHandler : ICommandHandler<ShipOrderCommand, Unit> { ... }

In that case the registration would become:

container.RegisterDecorator(typeof(ICommandHandler<,>), typeof(TransactionDecorator<,>), 
    c => c.ImplementationType.GetCustomAttribute<TransactionalAttribute>() != null);

Yet another option is to mark the command itself with an interface or inherit from a base class:

public class ShipOrderCommand : ICommand<Unit>, ITransactionalCommand
    public Guid OrderId;

This allows you to add a generic type constraint on the TransactionDecorator<,> and allows you to remove the predicate on the RegisterDecorator registration:

public class TransactionDecorator<int TCommand, out TResult>
    : ICommandHandler<TCommand, TResult>
    where TCommand : ITransactionalCommand
    // etc

Since Simple Injector understands type constraints, you can simplify the registration as follows:

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

Do note that I don't advice this last approach in this particular case, since implementing an ITransactionalCommand interface on the command again means that implementation details are leaking into the definition of the command. The command and its consumers don't need to know about whether transactions are needed on the command handler (and this is something that might change in the future).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download