using System.Collections.Generic;
public interface IMessage
[AttributeUsage(AttributeTargets.Method)]
public class HandlerAttribute : Attribute
public class MessageBroker
public IComponent Component;
public MethodInfo Method;
private Dictionary<Type, List<Handler>> m_messageHandlers = new Dictionary<Type, List<Handler>>();
public MessageBroker(List<IComponent> components)
foreach (var component in components)
var componentType = component.GetType();
var methods = componentType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
foreach (var method in methods)
var handlesAttributes = (HandlerAttribute[])method.GetCustomAttributes(typeof(HandlerAttribute), false);
if (handlesAttributes.Length != 1)
var parameters = method.GetParameters();
if (parameters.Length != 1)
Console.WriteLine(string.Format("Method {0} has too many arguments", method.Name));
if (!typeof(IMessage).IsAssignableFrom(parameters[0].ParameterType))
Console.WriteLine(string.Format("Method {0} does not have an IMessage as an argument", method.Name));
RegisterHandler(parameters[0].ParameterType, component, method);
private void RegisterHandler(Type messageType, IComponent component, MethodInfo methodInfo)
List<Handler> handlers = null;
if (!m_messageHandlers.TryGetValue(messageType, out handlers))
handlers = new List<Handler>();
m_messageHandlers[messageType] = handlers;
var handler = new Handler() { Component = component, Method = methodInfo };
public void HandleMessage(IMessage message)
List<Handler> handlers = null;
var messageType = message.GetType();
if (m_messageHandlers.TryGetValue(messageType, out handlers))
foreach (var handler in handlers)
var target = handler.Component;
var methodInfo = handler.Method;
methodInfo.Invoke(target, new object[] { message });
Console.WriteLine(string.Format("No handler found for message of type {0}", messageType.FullName));
public interface IComponent
public class ExampleMessageA : IMessage
public class ExampleMessageB : IMessage
public class ExampleComponent : IComponent
public void HandleMessageA(ExampleMessageA message)
Console.WriteLine(string.Format("Handling message of type ExampleMessageA: {0}", message.GetType().FullName));
public void HandleMessageB(ExampleMessageB message)
Console.WriteLine(string.Format("Handling message of type ExampleMessageB: {0}", message.GetType().FullName));
public void HandleMessageA_WrongType(object foo)
Console.WriteLine(string.Format("HandleMessageA_WrongType: {0}", foo.GetType().FullName));
public void HandleMessageA_MultipleArgs(object foo, object bar)
Console.WriteLine(string.Format("HandleMessageA_WrongType: {0}", foo.GetType().FullName));
public static void Main()
var components = new List<IComponent>() { new ExampleComponent() };
var messageBroker = new MessageBroker(components);
var messageA = new ExampleMessageA();
messageBroker.HandleMessage(messageA);
var messageB = new ExampleMessageB();
messageBroker.HandleMessage(messageB);