Skip to content

How to do Control Flow via Polymorphism

Let's say you have n objects implementing an interface. Call these message, implementing IMessage. Each message may cause a different action when given to another object, the receiver. Sounds like the perfect scenario for Polymorphism. Create a method Handle() for each of the n messages specifying the concrete type in the signature. Now, let's say you receive that message from a MessageFactory and, obviously, that factory hands you the message via the interface. So here's the pseudo code:

public interface IMessage
{
}

public class MessageA : IMessage
{
}

public class MessageB : IMessage
{
}

public class Receiver
{
  public void Handle(MessageA msg)
  {
  }

  public void Handle(MessageB msg)
  {
  }
}

public class MessageFactory
{
  public static IMessage GetMessage()
  {
  }
}

Now, how do you pass this message off to the appropriate Handle() version? You can't just call Handle() with your message because you message is actually an IMessage not the concrete type. I can think of three workarounds and don't like any of them. Is there another way, or is this just a limitation of C#? In the meantime, here are the three ways I can think of solving this:

The Switch

The traditional way, use if/else or switch to examine the incoming object and dispatch it. Just create a method Handle(IMessage msg) and have it dispatch each to the proper Handle(). Traditional, simple. But as n increases it becomes less and less readable and dispatch is now a runtime decision. It could just fail, if you overlooked a concrete class.

The Reflection

At runtime examine the actual type of the message and then inspect your receiver to dynamically invoke the appropriate methods. No worries about maintaining the code or readability. It's just magic... but runtime magic which may yet fail if you overlooked a concrete class.

The Self-Dispatcher

There is probably a named pattern that goes with this approach. It shares some aspects with the Visitor pattern (that's what inspired me actually), but I don't know what this pattern is actually called. The idea is that each message doesn't get passed to the receiver but passes itself. I.e. it calls the appropriate method. For this to work, we add a method to our interface:

public interface IMessage
{
  void Dispatch(Receiver receiver);
}

public class MessageA : IMessage
{
  public void Dispatch(Receiver receiver)
  {
    receiver.Handle(this);
  }
}

This works perfectly. After getting the message from the factory, you just call msg.Dispatch(receiver). Since each message implements its own dispatch for itself, we get compile time checking. Yay. But we basically copy and paste the Dispatch() method into every message class and we can't factor it into a common base-class, because that would break the flow control again. So it achieves the ends I'm after, but I don't like the implementation.

What other options are there?