I am trying to port this example of dynamic double dispatching to C#. I've got the example to work, but I feel like I've shortcut the DynamicDispatch
method in the MessageBase
class a bit by using Reflection to create the required handler and invoke the appropriate method. Could any provide some advice on how to change it? The example uses the C++ dynamic_cast operator and I'm not sure what the equivalent would be for C#. I'm not sure my solution is the right/best way.
Note: I'm using 3.5 so I can not use the dynamic keyword
Here is the code:
IMessage
public interface IMessage
{
void Dispatch(IHandler handler);
}
MessageBase
public abstract class MessageBase : IMessage
{
public abstract void Dispatch(IHandler handler);
// This is my concern, doesnt feel like the right way to do this
protected void DynamicDispatch<MessageType>(IHandler handler, MessageType self)
{
// Get the messages derived type
Type self_type = self.GetType();
// Create actual message specific handler
Type message_handler = typeof(IMessageHandler<>).MakeGenericType(self_type);
// Get the ProcessMessage method
MethodInfo minfo = message_handler.GetMethod("ProcessMessage");
try
{
// Invoke it with the message
minfo.Invoke(handler, new object[] { self });
}
catch (TargetException ex)
{
// Ignore if method doesnt exist
}
}
}
Message
public class Message : MessageBase
{
public override void Dispatch(IHandler handler)
{
DynamicDispatch(handler, this);
}
}
IHandler
public interface IHandler
{
}
IMessageHandler
public interface IMessageHandler<MessageType> : IHandler
{
void ProcessMessage(MessageType message);
}
DerivedMessageOne
public class DerivedMessageOne : Message
{
public int MessageOneField;
}
DerivedMessageTwo
public class DerivedMessageTwo : Message
{
public int MessageTwoField;
}
DerivedMessageHandlerOne
public class DerivedMessageHandlerOne : IMessageHandler<DerivedMessageOne>,
IMessageHandler<DerivedMessageTwo>
{
#region IMessageHandler<MessaegType> Members
// ************ handle both messages *************** //
public void ProcessMessage(DerivedMessageOne message)
{
// Received Message one, do soemthing with i
int do_something_with_it = message.MessageOneField;
}
public void ProcessMessage(DerivedMessageTwo message)
{
// Received Message two, do soemthing with i
}
#endregion
}
DerivedMessageHandlerTwo
public class DerivedMessageHandlerTwo : IMessageHandler<DerivedMessageOne>
{
#region IMessageHandler<MessaegType> Members
// ************ handle just MessageOne *************** //
public void ProcessMessage(DerivedMessageOne message)
{
// Received Message one, do soemthing with i
}
#endregion
}
Test Case
IMessage messageOne = new DerivedMessageOne();
IMessage messageTwo = new DerivedMessageTwo();
IHandler handlerOne = new DerivedMessageHandlerOne();
IHandler handlerTwo = new DerivedMessageHandlerTwo();
messageOne.Dispatch(handlerOne);
messageOne.Dispatch(handlerTwo);
messageTwo.Dispatch(handlerOne);
messageTwo.Dispatch(handlerTwo);