1

I try to find a simple way to resolve my handlers. The solution is "handling different types of messages". but each solution I found such as this idea, I stuck in resolving the handler because my handler has a constructor which has some dependencies to other interfaces.

For example, if I follow the mentioned idea my OrderMessageHandler is

public class OrderMessageHandler
{
    private readonly IInterface _interface;
    public OrderMessageHandler(IInterface interface) {_inteface=interface}

    bool HandleMessage( IMessage msg ) {
        if ( !(msg is OrderMessage)) return false;
        return true; 
    }
}

However that IInterface has other dependencies and I can not simply resolve that. I wonder if anyone has a better idea than this below class?

public class MessageProcessor {
    private List<IMessageHandler> handlers;

    public MessageProcessor() {
       handlers = new List<IMessageHandler>();
       handlers.add(new SomeOtherMessageHandler());
       handlers.add(new OrderMessageHandler());
    }

    public void ProcessMessage( IMessage msg ) {
       bool messageWasHandled
       foreach( IMessageHandler handler in handlers ) {
           if ( handler.HandleMessage(msg) ) {
               messageWasHandled = true;
               break;
           }
       }

       if ( !messageWasHandled ) {
          // Do some default processing, throw error, whatever.
       }
    }
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
ShrnPrmshr
  • 353
  • 2
  • 5
  • 17
  • Have you tried making your `IMessageHandler` interface generic, e.g. `IMessageHandler`? This is a very common approach and will get rid of all the type checking that you are currently doing. – Steven Oct 08 '19 at 14:49
  • @Steven I did that. my main problem is this message Processor to find the correct handler in a clean and easy way. I solved it but it seems very complex and lack of readability. I used both Activator.CreateInstance or even by invoking. I am not happy by those – ShrnPrmshr Oct 09 '19 at 06:03

1 Answers1

3

Following Explicit Dependencies Principle, you can ensure that all necessary dependencies are injected where.

public class MessageProcessor {
    private List<IMessageHandler> handlers;

    public MessageProcessor(IEnumerable<IMessageHandler> handlers) {
        this.handlers = new List<IMessageHandler>(handlers);
        //removed
        //handlers.add(new SomeOtherMessageHandler()); 
        //handlers.add(new OrderMessageHandler());
    }

    public void ProcessMessage( IMessage msg ) {
       bool messageWasHandled
       foreach( IMessageHandler handler in handlers ) {
           if ( handler.HandleMessage(msg) ) {
               messageWasHandled = true;
               break;
           }
       }

       if ( !messageWasHandled ) {
          // Do some default processing, throw error, whatever.
       }
    }
}

If using a DI container, make sure to register all parties involved

pseudocode:

container.Register<IInterface, Implementation>();
container.Register<IMessageHandler, SomeOtherMessageHandler>();
container.Register<IMessageHandler, OrderMessageHandler>();
container.Register<MessageProcessor>();

That way the container know how to build the object graph when resolving desired type

MessageProcessor processor = container.Resolve<MessageProcessor>();

processor.ProcessMessage(...);

//...

If using Pure DI this still allows for all types involved to be properly created and injected where needed.

IInterface dependency = new Implementation();
List<IMessageHandler> handlers = new List<IMessageHandler>();
handlers.Add(new SomeOtherMessageHandler()); 
handlers.Add(new OrderMessageHandler(dependency));
MessageProcessor processor = new MessageProcessor(handlers);

processor.ProcessMessage(...);

//...
Nkosi
  • 235,767
  • 35
  • 427
  • 472