2016-09-02 2 views
2

en train de passer loin de la manipulation des commandes de synchronisation et de les placer sur un bus de messages afin qu'ils puissent être traités plus tard, mais des problèmes revenir le type réel lorsque vous essayez de charger des commandes de type plutôt que chacun descommandes Resolve de bus

Voici ce que j'ai jusqu'à présent et semble fonctionner correctement

commande 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); 
    } 

aux commandes abonner

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

Gestion des messages

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

     handler.Handle(command); 
    } 

Je veux essentiellement de résoudre mes messages par convention afin Heres ce que je veux aller vers de si je ne dois taper chaque type de commande, mais ayant des problèmes à obtenir le type de retour

 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); 

      }); 
     } 

maintenant x est juste un objet que je ne peux pas passer à la méthode HandleCommand

Im en utilisant autofac pour mon conteneur et easynetq pour mon bus.

Répondre

0

Je pense que cette partie:

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

     handler.Handle(command); 
    } 

est fait pour vous par le AutoSubscriber, si vous implémentez IConsume<T> au lieu de ICommandHandler<T>, ils semblent avoir le même but.

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

Y at-il une raison particulière pour laquelle vous avez besoin d'une interface ICommandHandler<T> séparée? Sur une autre note: Dans votre implémentation, vous ne créez pas une 'portée' distincte lorsque vous résolvez les gestionnaires de commandes, ce qui provoque la vie éternelle de chaque instnace du gestionnaire (et des dépendances) dans la portée 'root'. En d'autres termes: une fuite de mémoire :)

Si vous voulez continuer à en tenir à votre mise en œuvre, je pense qu'il est préférable de faire quelque chose comme ceci:

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); 
     } 
    } 

Cependant, c'est ce que le AutofacMessageDispatcher fera pour si vous utilisez le AutoSubscriber:

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

+0

Ceci est très intéressant! Cependant, IConsume me laisserait avec une dépendance sur easynetQ. Comme je suis en train de penser à masstransit cela pourrait être une mauvaise dépendance – Luke

+0

@luke: IMHO je dirais remplacer IConsume avec IConsumer partout est plus facile que d'essayer de réimplémenter les concepts qui sont déjà là! –

+0

D'accord :) Merci pour votre aide, déplaçant mal à l'autosubscriber – Luke