public static class EventBus { private static Dictionary<Type, List<Action<object>>> handlers = new Dictionary<Type, List<Action<object>>>(); public static void Subscribe<T>(Action<T> handler){ if (!handlers.ContainsKey(typeof(T))) handlers.Add(typeof(T), new List<Action<object>>()); handlers[typeof(T)].Add(e => handler((T)e)); } public static void Publish<T>(T e){ var eventType = typeof(T); foreach (Type handlerType in handlers.Keys) TryPublishForType(handlerType, eventType, e); } private static void TryPublishForType(Type handlerType, Type eventType, object e){ if (handlerType.IsAssignableFrom(eventType)) handlers[handlerType].ForEach(handler => handler(e)); } }
It's very similar to the simplest event bus. I'm sure there are other ways of tracking what subscribers can handle each event but the Dictionary<Type, List<Action<object>>> works well enough. If you're not used to Haskell or C# type trickery then it may seem too complex either way but I think much of that is caused by how verbose C# tends to be.
One neat thing about typesafe event busses is that, if designed for it like this one is, they can respect the inheritance tree. That means if an Action<object> is subscribed, then it will get everything that get's published since all events are assignable to object. This also means that it is backwards compatible with the simplest EventBus. A few subscribers may need to explicitly state the event type they are interested in but if they use object as the type parameter when subscribing, then the behavior should be the same.
No comments:
Post a Comment