Dynamically call a method on a generic target

c#, generics, reflection

Solution

Most DI containers (including Ninject) allow you to do something like this:

public void Dispatch<T>(T command) where T : ICommand
{
    ICommandHandler<T> handler = IoC.Get<ICommandHandler<T>>();
    handler.Handle(command);
}

If you don't know the type of command (in other words, if `typeof(T) != command.GetType()`), using double-dispatch is the easiest way:

class SomeCommand : ICommand
{
    // ...

    public void Dispatch(IoC ioc)
    {
        var handler = ioc.Get<IHandle<SomeCommand>>();
        handler.Handle(this);
    }
}

but you could go with reflection if you find adding this code to all Commands distasteful.

Edit Here is a reflection-based version. You can (and should) cache the compiled delegate.

interface ICommand { }
interface IHandle<TCommand> where TCommand : ICommand
{
    void Handle(TCommand command);
}

class CreateUserCommand : ICommand { }
class CreateUserHandler : IHandle<CreateUserCommand>
{
    public void Handle(CreateUserCommand command)
    {
        Console.Write("hello");
    }
}

[TestMethod]
public void build_expression()
{
    object command = new CreateUserCommand();
    object handler = new CreateUserHandler();

    Action<object, object> dispatcher = BuildDispatcher(command.GetType());
    dispatcher(handler, command);
}

private static Action<object, object> BuildDispatcher(Type commandType)
{
    var handlerType = typeof(IHandle<>).MakeGenericType(commandType);
    var handleMethod = handlerType.GetMethod("Handle");

    var param1 = Expression.Parameter(typeof(object));
    var param2 = Expression.Parameter(typeof(object));

    var handler = Expression.ConvertChecked(param1, handlerType);
    var command = Expression.ConvertChecked(param2, commandType);
    var call = Expression.Call(handler, handleMethod, command);

    var lambda = Expression.Lambda<Action<object, object>>(call, param1, param2);
    return lambda.Compile();
}

Problem

I have a generic interface `ICommandHandler<>` that will have a number of implementations each for processing a specific implementation of `ICommand`, e.g.: ``` public class CreateUserCommand : ICommand { ... } public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand> { ... } ``` When I'm given an `ICommand` object I'm trying to dispatch it dynamically to the correct `ICommandHandler`. At the moment I've used a pretty straightforward reflection approach with an `Invoke` in my dispatcher class: ``` public void Dispatch<T>(T command) where T : ICommand { Type commandType = command.GetType(); Type handlerType = typeof(ICommandHandler<>).MakeGenericType(commandType); object handler = IoC.Get(handlerType); MethodInfo method = handlerType.GetMethod("Handle"); method.Invoke(handler, new object[] { command }); } ``` There are 2 problems with this approach. Firstly it uses slow reflection. Secondly if the method throws any kind of exception then it'll be wrapped in a `TargetInvocationException` and I'll lose the stack trace if I re-throw it. I worked out a way to make the call by creating a delegate and using `DynamicInvoke` but this doesn't solve the problem with exceptions (and I'm not sure `DynamicInvoke` is really any better than `Invoke`): ``` public void Dispatch<T>(T command) where T : ICommand { Type commandType = command.GetType(); Type handlerType = typeof(ICommandHandler<>).MakeGenericType(commandType); object handler = IoC.Get(handlerType); MethodInfo method = handlerType.GetMethod("Handle"); Type actionType = typeof(Action<>).MakeGenericType(commandType); Delegate action = Delegate.CreateDelegate(actionType, handler, method); action.DynamicInvoke(command); } ``` My question is, is there a better way to achieve what I'm trying to do? Preferably I could make a strongly-typed call instead of getting an `object` and looking up the `MethodInfo`. I assume that's not possible though because the type isn't know at compile time. If that's not possible then an efficient solution that would throw the exception more 'natively' would be the next best option. Edit: Updated code samples to clarify that I'm using IoC (Ninject) to create the `ICommandHandler` at runtime, not `Activator.CreateInstance()` as I first put. Included an example of how this would be used as requested: ``` var command = new CreateUserCommand() { Name = "Adam Rodger" }; var dispatcher = new CommandDispatcher(); dispatcher.Dispatch(command); // this would send the message to CreateUserCommandHandler.Handle(command) // dynamically and any exceptions would come back 'natively' ``` Edit 2: As suggested below, I can't cast the result of `IoC.Get(handlerType)` to `ICommandHandler<T>` because I get an `InvalidCastException` at runtime. This is because at runtime `T` is actually `ICommand`, I assume because the command classes are arriving over WCF and somehow manage to lose their strong typing. The code that calls the dispatcher looks something like: ``` [ServiceContract] public class CommandService { [OperationContract] public void Execute(ICommand command) // no type information { var dispatcher = new CommandDispatcher(); // injected by IoC in real version dispatcher.Dispatch(command); } } ```

Original source