using System.Collections.Generic;
public void Main() { R(); }
public abstract class EventBase { }
public abstract class MouseEvent : EventBase{}
public class MouseUpEvent : MouseEvent { }
public class MouseDownEvent : MouseEvent { }
public abstract class KeyboardEvent : EventBase{}
private Dictionary<string, Delegate> _dict = new Dictionary<string, Delegate>();
public void Dispatch(EventBase eventBase)
var t = eventBase.GetType();
while (t != typeof(EventBase))
if (_dict.TryGetValue(t.AssemblyQualifiedName, out d))
d.DynamicInvoke(eventBase);
public void Register(string assemblyQualifiedName, Delegate handler)
_dict.Add(assemblyQualifiedName, handler);
public void Unregister(string assemblyQualifiedName, Delegate handler)
_dict.Remove(assemblyQualifiedName);
public class VisualElement2
public Dispatcher Dispatcher;
public void Dispatch(EventBase e)
public void Register<T>(System.Action<T> handler) where T : EventBase
Dispatcher.Register(typeof(T).AssemblyQualifiedName, (System.Delegate) handler);
public void Unregister<T>(System.Action<T> handler) where T : EventBase
Dispatcher.Unregister(typeof(T).AssemblyQualifiedName, (System.Delegate)handler);
var d = new Dispatcher();
VisualElement2 ve = new VisualElement2() {Dispatcher = d};
ve.Register<MouseDownEvent>(OnMouseDown);
ve.Register<MouseUpEvent>(OnMouseUp);
ve.Register<MouseEvent>(OnMouse);
ve.Dispatch(new MouseDownEvent());
Assert.AreEqual(1, downCalled);
Assert.AreEqual(0, upCalled);
Assert.AreEqual(1, mouseCalled);
ve.Unregister<MouseDownEvent>(OnMouseDown);
ve.Dispatch(new MouseDownEvent());
Assert.AreEqual(1, downCalled);
Assert.AreEqual(0, upCalled);
Assert.AreEqual(2, mouseCalled);
Console.WriteLine("Done");
private void OnMouse(MouseEvent e)
private void OnMouseDown(MouseDownEvent e)
private void OnMouseUp(MouseUpEvent e)