2

Currently moving away from handling commands sync and placing them onto a message bus so they can be handled later but having problems getting back the real type when trying to to load commands rather then type each one out

Here is what I have so far and seems to work fine

Command Dispatcher

  public class CommandDispatcher : ICommandDispatcher
{
    private readonly IBus _commandBus;

    public CommandDispatcher(IBus commandBus)
    {
        _commandBus = commandBus;
    }

    public void Dispatch<TCommand>(TCommand command) where TCommand : ICommand
    {
        var messageType = typeof(TCommand);

        _commandBus.Publish(messageType, command);
    }

Subscribing to commands

  bus.Subscribe<CommandOne>("key", HandleCommand);
  bus.Subscribe<CommandTwo>("key", HandleCommand);

Handling messages

   private void HandleCommand<TCommand>(TCommand command) where TCommand : ICommand
    {
        var handler = _container.Resolve<ICommandHandler<TCommand>>();

        handler.Handle(command);
    }

I basically want to resolve my messages by convention so heres what I want to move towards to so I dont have to type each command type but having issues getting the type back

        var commandAssembly = Assembly.GetAssembly(typeof(ICommand));

        var commands = commandAssembly.GetTypes().Where(x => typeof(ICommand).IsAssignableFrom(x));

        foreach (var command in commands)
        {
            bus.Subscribe(command, "key", x =>
            {
                HandleCommand(x);

            });
        }

Now x is just an object that I cannot pass to the Handlecommand method

Im using autofac for my container and easynetq for my bus.

Luke
  • 59
  • 1
  • 6

1 Answers1

0

I think this part:

   private void HandleCommand<TCommand>(TCommand command) where TCommand : ICommand
    {
        var handler = _container.Resolve<ICommandHandler<TCommand>>();

        handler.Handle(command);
    }

Is all done for you by the AutoSubscriber, if you implement IConsume<T> instead of ICommandHandler<T>, they seem to have the same purpose.

https://github.com/EasyNetQ/EasyNetQ/wiki/Auto-Subscriber

Is there any specific reason why you need a separate ICommandHandler<T> interface?

On another note: In your implementation you're not creating a separate 'scope' when resolving the command handlers, causing every instnace of the handler (and any dependencies) to live forever in the 'root' scope. In other words: a memory leak :)

If you still want to stick with your implementation, I think it's better to do something like this:

   private void HandleCommand<TCommand>(TCommand command) where TCommand : ICommand
    {
        using(var scope = _container.BeginLifetimeScope("my-command-scope"))
        {
          var handler = scope.Resolve<ICommandHandler<TCommand>>();
          handler.Handle(command);
        }
    }

However, this is what the AutofacMessageDispatcher will do for you if you use the AutoSubscriber:

https://github.com/EasyNetQ/EasyNetQ/blob/master/Source/EasyNetQ.DI.Autofac/AutofacMessageDispatcher.cs

Wiebe Tijsma
  • 10,173
  • 5
  • 52
  • 68
  • This is very interesting! However, IConsume would leave me with a dependency on easynetQ. As I am currently thinking about masstransit this could be a bad dependency – Luke Sep 06 '16 at 23:40
  • @luke: IMHO I would say replacing IConsume with IConsumer everywhere is easier than trying to reimplement the concepts that are already there! – Wiebe Tijsma Sep 08 '16 at 08:51
  • Agreed :) Thanks for your help, ill moving to the autosubscriber – Luke Sep 09 '16 at 22:32