init
This commit is contained in:
193
Common/DTS.Common.Core/EventManager/EventManager.cs
Normal file
193
Common/DTS.Common.Core/EventManager/EventManager.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
namespace DTS.Common.Core.EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate used by event listeners
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="item"></param>
|
||||
public delegate void SubscriberCallbackDelegate<in T>(T item) where T : class;
|
||||
|
||||
public delegate void DiagnosticCallbackDelegate(EventDiagnosticType eventType, Type t, object eventData, string listener);
|
||||
|
||||
/// <summary>
|
||||
/// Allows components to publish events without knowing who is listening
|
||||
/// </summary>
|
||||
public static class EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Tracks listeners
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, List<object>> SubscriberList = new Dictionary<Type, List<object>>();
|
||||
|
||||
/// <summary>
|
||||
/// Tracks diagnostic listeners
|
||||
/// </summary>
|
||||
private static readonly List<DiagnosticCallbackDelegate> DiagnosticList = new List<DiagnosticCallbackDelegate>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Publish an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="eventData">event listener</param>
|
||||
public static void Publish<T>(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<T>;
|
||||
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?.Method);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void Subscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class
|
||||
{
|
||||
Subscribe(listener, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
/// <param name="eventFilter">predicate to filter events sent to event listener</param>
|
||||
public static void Subscribe<T>(SubscriberCallbackDelegate<T> listener, Predicate<T> eventFilter) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T)))
|
||||
{
|
||||
SubscriberList.Add(typeof(T), new List<object>());
|
||||
}
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
var metaData = new EventMetaData<T> { Callback = listener, EventFilter = eventFilter };
|
||||
|
||||
listeners.Add(metaData);
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.AddListener, typeof(T), null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows a subscriber to unsubscribe
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void UnSubscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T))) return;
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
listeners.RemoveAll(p =>
|
||||
{
|
||||
return p is EventMetaData<T> eventMetaData && eventMetaData.Callback == listener;
|
||||
});
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListener, typeof(T), null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all listeners
|
||||
/// </summary>
|
||||
public static void Clear()
|
||||
{
|
||||
SubscriberList.Clear();
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListener, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add diagnostic listener
|
||||
/// </summary>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void SubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)
|
||||
{
|
||||
DiagnosticList.Add(listener);
|
||||
SendDiagnosticEvent(EventDiagnosticType.AddListenerDiagnostic, null, null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear diagnostic event
|
||||
/// </summary>
|
||||
/// <param name="listener">listener to unsubscribe</param>
|
||||
public static void UnSubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)
|
||||
{
|
||||
DiagnosticList.RemoveAll(p => p == listener);
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all diagnostic events
|
||||
/// </summary>
|
||||
public static void ClearDiagnosticEvents()
|
||||
{
|
||||
DiagnosticList.Clear();
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a diagnostic event
|
||||
/// </summary>
|
||||
/// <param name="diagnosticEventType"></param>
|
||||
/// <param name="eventType"></param>
|
||||
/// <param name="eventData"></param>
|
||||
/// <param name="listenerMethod"></param>
|
||||
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 = $"{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
|
||||
}
|
||||
|
||||
internal class EventMetaData<T> where T : class
|
||||
{
|
||||
public Predicate<T> EventFilter { get; set; }
|
||||
public SubscriberCallbackDelegate<T> Callback { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user