using System; using System.Collections.Generic; using System.Reflection; namespace DataPro.Core.EventManager { /// /// Delegate used by event listeners /// /// /// public delegate void SubscriberCallbackDelegate(T item) where T : class; public delegate void DiagnosticCallbackDelegate(EventDiagnosticType eventType, Type t, object eventData, string listener); /// /// Allows components to publish events without knowing who is listening /// public static class EventManager { /// /// Tracks listeners /// private static readonly Dictionary> SubscriberList = new Dictionary>(); /// /// Tracks diagnostic listeners /// private static readonly List DiagnosticList = new List(); /// /// Publish an event /// /// type of event /// event listener public static void Publish(T eventData) where T : class { if (!SubscriberList.ContainsKey(typeof(T))) return; var listeners = SubscriberList[typeof(T)]; foreach (var listener in listeners) { var metaData = listener as EventMetaData; if (metaData == null) continue; var triggerCallback = true; if (metaData.EventFilter != null) { triggerCallback = metaData.EventFilter(eventData); } if (triggerCallback) { metaData.Callback(eventData); } SendDiagnosticEvent(EventDiagnosticType.PublishEvent, typeof(T), eventData, metaData.EventFilter != null ? metaData.EventFilter.Method : null); } } /// /// Subscribe to an event /// /// type of event /// event listener public static void Subscribe(SubscriberCallbackDelegate listener) where T : class { Subscribe(listener, null); } /// /// Subscribe to an event /// /// type of event /// event listener /// predicate to filter events sent to event listener public static void Subscribe(SubscriberCallbackDelegate listener, Predicate eventFilter) where T : class { if (!SubscriberList.ContainsKey(typeof(T))) { SubscriberList.Add(typeof(T), new List()); } var listeners = SubscriberList[typeof(T)]; var metaData = new EventMetaData { Callback = listener, EventFilter = eventFilter }; listeners.Add(metaData); SendDiagnosticEvent(EventDiagnosticType.AddListener, typeof(T), null, listener.Method); } /// /// Allows a subscriber to unsubscribe /// /// type of event /// event listener public static void UnSubscribe(SubscriberCallbackDelegate listener) where T : class { if (!SubscriberList.ContainsKey(typeof(T))) return; var listeners = SubscriberList[typeof(T)]; listeners.RemoveAll(p => { var eventMetaData = p as EventMetaData; return eventMetaData != null && eventMetaData.Callback == listener; }); SendDiagnosticEvent(EventDiagnosticType.RemoveListener, typeof(T), null, listener.Method); } /// /// Clears all listeners /// public static void Clear() { SubscriberList.Clear(); SendDiagnosticEvent(EventDiagnosticType.RemoveListener, null, null, null); } /// /// Add diagnostic listener /// /// event listener public static void SubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener) { DiagnosticList.Add(listener); SendDiagnosticEvent(EventDiagnosticType.AddListenerDiagnostic, null, null, listener.Method); } /// /// Clear diagnostic event /// /// listener to unsubscribe public static void UnSubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener) { DiagnosticList.RemoveAll(p => p == listener); SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, listener.Method); } /// /// Clear all diagnostic events /// public static void ClearDiagnosticEvents() { DiagnosticList.Clear(); SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, null); } /// /// Sends a diagnostic event /// /// /// /// /// private static void SendDiagnosticEvent(EventDiagnosticType diagnosticEventType, Type eventType, object eventData, MemberInfo listenerMethod) { foreach (var diagnosticEvent in DiagnosticList) { string listener = null; if (listenerMethod != null && listenerMethod.DeclaringType != null) { listener = string.Format("{0}.{1} , {2}", listenerMethod.DeclaringType.FullName, listenerMethod.Name, listenerMethod.DeclaringType.Assembly.FullName); } diagnosticEvent(diagnosticEventType, eventType, eventData, listener); } } } public enum EventDiagnosticType { AddListener = 0, AddListenerDiagnostic = 1, PublishEvent = 2, RemoveListenerDiagnostic = 3, RemoveListener = 4 } class EventMetaData where T : class { public Predicate EventFilter { get; set; } public SubscriberCallbackDelegate Callback { get; set; } } }