using System.Collections.Generic; using System; namespace Fungus { public class EventDispatcher { public delegate void TypedDelegate(T e) where T : class; #region Statics static EventDispatcher _instance; public static EventDispatcher Instance { get { if(_instance == null) { _instance = new EventDispatcher(); } return _instance; } } public static void AddLog(Action log) { Instance.addLog(log); } public static void RemoveLog(Action log) { Instance.removeLog(log); } public static void AddListener(TypedDelegate listener) where T : class { Instance.addListener(listener); } public static void RemoveListener(TypedDelegate listener) where T : class { Instance.removeListener(listener); } public static void Raise(T evt) where T : class { Instance.raise(evt); } public static void Raise() where T : class, new() { Instance.raise(new T()); } public static void UnregisterAll() { Instance.unregisterAll(); } #endregion #region Private Members readonly Dictionary> _delegates; event Action _onLog; #endregion #region Private Functions private EventDispatcher() { _delegates = new Dictionary>(); } /// /// Gets the delegate list copy. /// /// /// As listener can modify the list while iterating it, it is better to iterate a copy of the delegates list instead of a reference. /// /// A copy of the delegates list if found. Null if the dictionary does not contain a delegate list for this event. /// Event instance. /// Type of the received event. List getDelegateListCopy(T evt) { var type = typeof(T); return _delegates.ContainsKey(type) ? new List(_delegates[type]) : null; } void log(string message) { if(_onLog != null) { _onLog(message); } } #endregion #region Public Functions public void addLog(Action log) { _onLog += log; } public void removeLog(Action log) { _onLog -= log; } public void addListener(TypedDelegate listener) where T : class { var type = typeof(T); if(!_delegates.ContainsKey(type)) { _delegates.Add(type, new List()); } var list = _delegates[type]; if(!list.Contains(listener)) { list.Add(listener); } } public void removeListener(TypedDelegate listener) where T : class { var type = typeof(T); if(_delegates.ContainsKey(type)) { _delegates[type].Remove(listener); return; } } public void raise(T evt) where T : class { if(evt == null) { log("Raised a null event"); return; } var list = getDelegateListCopy(evt); if(list == null || list.Count < 1) { log("Raised an event with no listeners"); return; } for(int i = 0; i < list.Count; ++i) { var callback = list[i] as TypedDelegate; if(callback != null) { try { callback(evt); } catch(Exception gotcha) { log(gotcha.Message); } } } } public void raise() where T : class, new() { raise(new T()); } public void unregisterAll() { _delegates.Clear(); } #endregion } }