|
|
@ -8,64 +8,99 @@ using System.Text; |
|
|
|
|
|
|
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus |
|
|
|
{ |
|
|
|
public class InMemoryEventBusSubscriptionsManager : IEventBusSubscriptionsManager |
|
|
|
public partial class InMemoryEventBusSubscriptionsManager : IEventBusSubscriptionsManager |
|
|
|
{ |
|
|
|
private readonly Dictionary<string, List<Delegate>> _handlers; |
|
|
|
|
|
|
|
|
|
|
|
private readonly Dictionary<string, List<SubscriptionInfo>> _handlers; |
|
|
|
private readonly List<Type> _eventTypes; |
|
|
|
|
|
|
|
public event EventHandler<string> OnEventRemoved; |
|
|
|
|
|
|
|
public InMemoryEventBusSubscriptionsManager() |
|
|
|
{ |
|
|
|
_handlers = new Dictionary<string, List<Delegate>>(); |
|
|
|
_handlers = new Dictionary<string, List<SubscriptionInfo>>(); |
|
|
|
_eventTypes = new List<Type>(); |
|
|
|
} |
|
|
|
|
|
|
|
public bool IsEmpty => !_handlers.Keys.Any(); |
|
|
|
public void Clear() => _handlers.Clear(); |
|
|
|
|
|
|
|
public void AddSubscription<T, TH>(Func<TH> handler) |
|
|
|
public void AddDynamicSubscription<TH>(string eventName, Func<TH> handler) |
|
|
|
where TH : IDynamicIntegrationEventHandler |
|
|
|
{ |
|
|
|
DoAddSubscription(handler, eventName, isDynamic: true); |
|
|
|
} |
|
|
|
|
|
|
|
public void AddSubscription<T, TH>(Func<TH> handler) |
|
|
|
where T : IntegrationEvent |
|
|
|
where TH : IIntegrationEventHandler<T> |
|
|
|
{ |
|
|
|
var key = GetEventKey<T>(); |
|
|
|
if (!HasSubscriptionsForEvent<T>()) |
|
|
|
var eventName = GetEventKey<T>(); |
|
|
|
DoAddSubscription(handler, eventName, isDynamic: false); |
|
|
|
_eventTypes.Add(typeof(T)); |
|
|
|
} |
|
|
|
|
|
|
|
private void DoAddSubscription(Delegate handler, string eventName, bool isDynamic) |
|
|
|
{ |
|
|
|
if (!HasSubscriptionsForEvent(eventName)) |
|
|
|
{ |
|
|
|
_handlers.Add(key, new List<Delegate>()); |
|
|
|
_handlers.Add(eventName, new List<SubscriptionInfo>()); |
|
|
|
} |
|
|
|
_handlers[key].Add(handler); |
|
|
|
_eventTypes.Add(typeof(T)); |
|
|
|
if (isDynamic) |
|
|
|
{ |
|
|
|
_handlers[eventName].Add(SubscriptionInfo.Dynamic(handler)); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
_handlers[eventName].Add(SubscriptionInfo.Typed(handler)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void RemoveDynamicSubscription<TH>(string eventName) |
|
|
|
where TH : IDynamicIntegrationEventHandler |
|
|
|
{ |
|
|
|
var handlerToRemove = FindDynamicSubscriptionToRemove<TH>(eventName); |
|
|
|
DoRemoveHandler(eventName, handlerToRemove); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void RemoveSubscription<T, TH>() |
|
|
|
where TH : IIntegrationEventHandler<T> |
|
|
|
where T : IntegrationEvent |
|
|
|
{ |
|
|
|
var handlerToRemove = FindHandlerToRemove<T, TH>(); |
|
|
|
if (handlerToRemove != null) |
|
|
|
var handlerToRemove = FindSubscriptionToRemove<T, TH>(); |
|
|
|
var eventName = GetEventKey<T>(); |
|
|
|
DoRemoveHandler(eventName, handlerToRemove); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void DoRemoveHandler(string eventName, SubscriptionInfo subsToRemove) |
|
|
|
{ |
|
|
|
if (subsToRemove != null) |
|
|
|
{ |
|
|
|
var key = GetEventKey<T>(); |
|
|
|
_handlers[key].Remove(handlerToRemove); |
|
|
|
if (!_handlers[key].Any()) |
|
|
|
_handlers[eventName].Remove(subsToRemove); |
|
|
|
if (!_handlers[eventName].Any()) |
|
|
|
{ |
|
|
|
_handlers.Remove(key); |
|
|
|
var eventType = _eventTypes.SingleOrDefault(e => e.Name == key); |
|
|
|
_handlers.Remove(eventName); |
|
|
|
var eventType = _eventTypes.SingleOrDefault(e => e.Name == eventName); |
|
|
|
if (eventType != null) |
|
|
|
{ |
|
|
|
_eventTypes.Remove(eventType); |
|
|
|
RaiseOnEventRemoved(eventType.Name); |
|
|
|
} |
|
|
|
RaiseOnEventRemoved(eventName); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public IEnumerable<Delegate> GetHandlersForEvent<T>() where T : IntegrationEvent |
|
|
|
public IEnumerable<SubscriptionInfo> GetHandlersForEvent<T>() where T : IntegrationEvent |
|
|
|
{ |
|
|
|
var key = GetEventKey<T>(); |
|
|
|
return GetHandlersForEvent(key); |
|
|
|
} |
|
|
|
public IEnumerable<Delegate> GetHandlersForEvent(string eventName) => _handlers[eventName]; |
|
|
|
public IEnumerable<SubscriptionInfo> GetHandlersForEvent(string eventName) => _handlers[eventName]; |
|
|
|
|
|
|
|
private void RaiseOnEventRemoved(string eventName) |
|
|
|
{ |
|
|
@ -76,22 +111,34 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private Delegate FindHandlerToRemove<T, TH>() |
|
|
|
where T : IntegrationEvent |
|
|
|
where TH : IIntegrationEventHandler<T> |
|
|
|
|
|
|
|
private SubscriptionInfo FindDynamicSubscriptionToRemove<TH>(string eventName) |
|
|
|
where TH : IDynamicIntegrationEventHandler |
|
|
|
{ |
|
|
|
if (!HasSubscriptionsForEvent<T>()) |
|
|
|
return DoFindHandlerToRemove(eventName, typeof(TH)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private SubscriptionInfo FindSubscriptionToRemove<T, TH>() |
|
|
|
where T : IntegrationEvent |
|
|
|
where TH : IIntegrationEventHandler<T> |
|
|
|
{ |
|
|
|
var eventName = GetEventKey<T>(); |
|
|
|
return DoFindHandlerToRemove(eventName, typeof(TH)); |
|
|
|
} |
|
|
|
|
|
|
|
private SubscriptionInfo DoFindHandlerToRemove(string eventName, Type handlerType) |
|
|
|
{ |
|
|
|
if (!HasSubscriptionsForEvent(eventName)) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
var key = GetEventKey<T>(); |
|
|
|
foreach (var func in _handlers[key]) |
|
|
|
foreach (var subscription in _handlers[eventName]) |
|
|
|
{ |
|
|
|
var genericArgs = func.GetType().GetGenericArguments(); |
|
|
|
if (genericArgs.SingleOrDefault() == typeof(TH)) |
|
|
|
var genericArgs = subscription.Factory.GetType().GetGenericArguments(); |
|
|
|
if (genericArgs.SingleOrDefault() == handlerType) |
|
|
|
{ |
|
|
|
return func; |
|
|
|
return subscription; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -104,10 +151,10 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus |
|
|
|
return HasSubscriptionsForEvent(key); |
|
|
|
} |
|
|
|
public bool HasSubscriptionsForEvent(string eventName) => _handlers.ContainsKey(eventName); |
|
|
|
|
|
|
|
public Type GetEventTypeByName(string eventName) => _eventTypes.Single(t => t.Name == eventName); |
|
|
|
|
|
|
|
private string GetEventKey<T>() |
|
|
|
public Type GetEventTypeByName(string eventName) => _eventTypes.SingleOrDefault(t => t.Name == eventName); |
|
|
|
|
|
|
|
public string GetEventKey<T>() |
|
|
|
{ |
|
|
|
return typeof(T).Name; |
|
|
|
} |
|
|
|