A way to handle open generics using Simple Injector

In case I need to do this again, this works, however ‘ugly’ it might be.  This isn’t supposed to be a best practice or anything (there are no such things as best practices, and even if there were some, I wouldn’t know them, since I’m not a very good developer).

Some code:

public interface ICommand {}

public interface ICommand<TReturnValue> : ICommand
        TReturnValue ReturnValue { get; set; }

public class Command : ICommand  {}

public class Command<TReturnValue> : ICommand<TReturnValue>
        public TReturnValue ReturnValue { get; set; }

There’s more to commands than this, but this will suffice.  And yes, I know that some people don’t like commands that return values.  That’s nice.

So now, I want to be able to handle them.

public interface Handles<T, TReturnValue> where T : ICommand<TReturnValue>
        TReturnValue Handle(T command);

public interface Handles<T> where T : ICommand
        void Handle(T command);

Simple enough.

Now, I need to be able to publish commands.

public interface ICommandBaseBus
        void Publish<TCommand>(TCommand command) where TCommand : Command;
        TReturnValue Publish<TCommand, TReturnValue>(TCommand command) where TCommand : Command<TReturnValue>;

Still quite simple.

Now, here’s where Simple Injector comes in.  I don’t want to ‘hand’ register these things together, I want to just scan that sort of stuff.

I tried Autofac, Ninject, StructureMap, and Simple Injector.  I am showing how to do it with Simple Injector because, well, it’s the first one I got to work.  There’s no other reason than that.

Let’s implement the bus.

public class CommandBaseBus : ICommandBaseBus
    private Container _container; 

    public CommandBaseBus()
        _container = new Container();

(serviceType, implTypes) => _container.RegisterAll(serviceType, implTypes),

(serviceType, implTypes) => _container.RegisterAll(serviceType, implTypes),


A few things of note:

You need to specify using SimpleInjector.Extensions namespace to get the RegisterMany…. method, which does the fun automagic stuff of connecting your handlers with the relevant commands.

It can get more complicated than this, which I will show in a subsequent post.

I like the Verify() call.  A lot.  I have a tendency to forget to do things, and so when I was ‘hand’ registering stuff, I’d forget to check if everything was wired up correctly, and so get a bunch of run-time barfdom.   If you have the container manage everything, you get that ‘fail fast’ thing immediately when you fire up the bus.

Your calling code might look like this:

static void Main()
            var cmdBus = new CommandBaseBus();

            var myCommand = new MyCommand();
            var myCommandWithReturnValue = new MyCommandWithReturnValue();

            var rv = cmdBus.Publish<MyCommandWithReturnValue, bool>(myCommandWithReturnValue);

MyCommandWithReturnValue implements Command<bool> here.

And when you publish, it might do something like this:

public void Publish<TCommand>(TCommand command) where TCommand : Command
            var regs = _container.GetAllInstances<Handles<TCommand>>();

            foreach(var r in regs)

            //if (!(command is IVariableResult))
               // _eventBus.Process(command);


public TReturnValue Publish<TCommand, TReturnValue>(TCommand command) where TCommand : Command<TReturnValue>
            var regs = _container.GetAllInstances<Handles<TCommand, TReturnValue>>().ToList();

            Handles<TCommand, TReturnValue> r = regs[0];

            TReturnValue trv = r.Handle(command);

            //if(!(command is IVariableResult))
            //    _eventBus.Process<TCommand, TReturnValue>(command);

            return trv;

Ignore the commented out stuff about event bus processing and IVariableResult, I’ll get to that some other time.  Maybe.

And yes, I know that normally you would only have one handler for a command, and yes, I know that my variable names suck.

This takes care of, well, the stuff I care gets taken care of at the moment.

posted on Tuesday, December 30, 2014 9:12 PM Print
No comments posted yet.

Post Comment

Title *
Name *
Comment *  
Please add 3 and 3 and type the answer here: