using System.Collections.Generic;
public interface IEvent {}
public struct DialogEvent : IEvent { public string Dialog; }
public delegate void EventCallback<T>(T data);
public class EventManager
private static Dictionary<Type, Delegate> _delegates = new Dictionary<Type, Delegate>();
private static Dictionary<Type, Delegate> _idelegates = new Dictionary<Type, Delegate>();
public static void AddEventListener<T>(EventCallback<T> listener)
AddEventListenerImpl(typeof(T), listener, _delegates);
public static void AddIEventListener(Type t, EventCallback<IEvent> listener)
AddEventListenerImpl(t, listener, _idelegates);
public static void AddEventListenerImpl<T>(Type t, EventCallback<T> listener, Dictionary<Type, Delegate> delegates)
if (delegates.TryGetValue(t, out d))
delegates[t] = Delegate.Combine(d, listener);
public static void TriggerEvent<T>(T e) where T : IEvent
if (_delegates.TryGetValue(typeof(T), out d))
EventCallback<T> callback = d as EventCallback<T>;
Console.WriteLine("Found " + e + " in <T>=" + typeof(T) + " (delegates)");
if (_idelegates.TryGetValue(e.GetType(), out d2))
EventCallback<IEvent> callback2 = d2 as EventCallback<IEvent>;
Console.WriteLine("Found " + e + " in t=" + e.GetType() + " (idelegates)");
public static void RemoveEventListener<T>(EventCallback<T> listener)
RemoveEventListenerImpl(typeof(T), listener, _delegates);
public static void RemoveIEventListener(Type t, EventCallback<IEvent> listener)
RemoveEventListenerImpl<IEvent>(t, listener, _idelegates, true);
public static void RemoveEventListenerImpl<T>(Type t, EventCallback<T> listener, Dictionary<Type, Delegate> delegates, bool isIEvent = false)
if (delegates.TryGetValue(t, out d))
Delegate currentDel = Delegate.Remove(d, listener);
delegates[t] = currentDel;
private void OnDialogEvent(IEvent e)
Console.WriteLine("--------------------------");
Console.WriteLine("IEVENT HANDLER");
Console.WriteLine("OnDialogEvent(IEvent e) " + e);
Console.WriteLine("routing ===>");
OnDialogEvent((DialogEvent)e);
private void OnDialogEvent(DialogEvent e)
Console.WriteLine("--------------------------");
Console.WriteLine("CONCRETE HANDLER");
Console.WriteLine("OnDialogEvent(DialogEvent e) " + e);
Console.WriteLine("=====> " + e.Dialog);
Console.WriteLine("--------------------------");
DialogEvent helloDialogEvent = new DialogEvent { Dialog = "Hello" };
IEvent helloEventAsIEvent = (IEvent)helloDialogEvent;
DialogEvent worldDialogEvent = new DialogEvent { Dialog = "World" };
DialogEvent fooDialogEvent = new DialogEvent { Dialog = "Foo" };
EventManager.AddEventListener<DialogEvent>(OnDialogEvent);
EventManager.AddIEventListener(typeof(DialogEvent), OnDialogEvent);
Console.WriteLine("*** IEvent trigger ***");
EventManager.TriggerEvent(helloEventAsIEvent);
Console.WriteLine("*** concrete trigger ***");
EventManager.TriggerEvent(worldDialogEvent);
Console.WriteLine("*** trigger ConcreteEvent both ways with <T> ***");
EventManager.TriggerEvent<IEvent>(fooDialogEvent);
EventManager.TriggerEvent<DialogEvent>(fooDialogEvent);
Console.WriteLine("*** trigger IEvent both ways with <T> ***");
EventManager.TriggerEvent<DialogEvent>(helloDialogEvent);
EventManager.TriggerEvent<IEvent>(helloDialogEvent);
Console.WriteLine("==== remove listeners ====");
EventManager.RemoveEventListener<DialogEvent>(OnDialogEvent);
EventManager.RemoveIEventListener(typeof(DialogEvent), OnDialogEvent);