|
@ -3,160 +3,135 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; |
|
|
using System; |
|
|
using System; |
|
|
using System.Collections.Generic; |
|
|
using System.Collections.Generic; |
|
|
using System.Linq; |
|
|
using System.Linq; |
|
|
using System.Reflection; |
|
|
|
|
|
using System.Text; |
|
|
|
|
|
|
|
|
|
|
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus |
|
|
namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus |
|
|
{ |
|
|
{ |
|
|
public partial class InMemoryEventBusSubscriptionsManager : IEventBusSubscriptionsManager |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private readonly Dictionary<string, List<SubscriptionInfo>> _handlers; |
|
|
|
|
|
private readonly List<Type> _eventTypes; |
|
|
|
|
|
|
|
|
|
|
|
public event EventHandler<string> OnEventRemoved; |
|
|
|
|
|
|
|
|
|
|
|
public InMemoryEventBusSubscriptionsManager() |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers = new Dictionary<string, List<SubscriptionInfo>>(); |
|
|
|
|
|
_eventTypes = new List<Type>(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public bool IsEmpty => !_handlers.Keys.Any(); |
|
|
|
|
|
public void Clear() => _handlers.Clear(); |
|
|
|
|
|
|
|
|
|
|
|
public void AddDynamicSubscription<TH>(string eventName) |
|
|
|
|
|
where TH : IDynamicIntegrationEventHandler |
|
|
|
|
|
{ |
|
|
|
|
|
DoAddSubscription(typeof(TH), eventName, isDynamic: true); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void AddSubscription<T, TH>() |
|
|
|
|
|
where T : IntegrationEvent |
|
|
|
|
|
where TH : IIntegrationEventHandler<T> |
|
|
|
|
|
{ |
|
|
|
|
|
var eventName = GetEventKey<T>(); |
|
|
|
|
|
DoAddSubscription(typeof(TH), eventName, isDynamic: false); |
|
|
|
|
|
_eventTypes.Add(typeof(T)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void DoAddSubscription(Type handlerType, string eventName, bool isDynamic) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!HasSubscriptionsForEvent(eventName)) |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers.Add(eventName, new List<SubscriptionInfo>()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (_handlers[eventName].Any(s => s.HandlerType == handlerType)) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ArgumentException( |
|
|
|
|
|
$"Handler Type {handlerType.Name} already registered for '{eventName}'", nameof(handlerType)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (isDynamic) |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers[eventName].Add(SubscriptionInfo.Dynamic(handlerType)); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers[eventName].Add(SubscriptionInfo.Typed(handlerType)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 = FindSubscriptionToRemove<T, TH>(); |
|
|
|
|
|
var eventName = GetEventKey<T>(); |
|
|
|
|
|
DoRemoveHandler(eventName, handlerToRemove); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void DoRemoveHandler(string eventName, SubscriptionInfo subsToRemove) |
|
|
|
|
|
{ |
|
|
|
|
|
if (subsToRemove != null) |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers[eventName].Remove(subsToRemove); |
|
|
|
|
|
if (!_handlers[eventName].Any()) |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers.Remove(eventName); |
|
|
|
|
|
var eventType = _eventTypes.SingleOrDefault(e => e.Name == eventName); |
|
|
|
|
|
if (eventType != null) |
|
|
|
|
|
{ |
|
|
|
|
|
_eventTypes.Remove(eventType); |
|
|
|
|
|
} |
|
|
|
|
|
RaiseOnEventRemoved(eventName); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public IEnumerable<SubscriptionInfo> GetHandlersForEvent<T>() where T : IntegrationEvent |
|
|
|
|
|
{ |
|
|
|
|
|
var key = GetEventKey<T>(); |
|
|
|
|
|
return GetHandlersForEvent(key); |
|
|
|
|
|
} |
|
|
|
|
|
public IEnumerable<SubscriptionInfo> GetHandlersForEvent(string eventName) => _handlers[eventName]; |
|
|
|
|
|
|
|
|
|
|
|
private void RaiseOnEventRemoved(string eventName) |
|
|
|
|
|
{ |
|
|
|
|
|
var handler = OnEventRemoved; |
|
|
|
|
|
if (handler != null) |
|
|
|
|
|
{ |
|
|
|
|
|
OnEventRemoved(this, eventName); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private SubscriptionInfo FindDynamicSubscriptionToRemove<TH>(string eventName) |
|
|
|
|
|
where TH : IDynamicIntegrationEventHandler |
|
|
|
|
|
{ |
|
|
|
|
|
return DoFindSubscriptionToRemove(eventName, typeof(TH)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private SubscriptionInfo FindSubscriptionToRemove<T, TH>() |
|
|
|
|
|
where T : IntegrationEvent |
|
|
|
|
|
where TH : IIntegrationEventHandler<T> |
|
|
|
|
|
{ |
|
|
|
|
|
var eventName = GetEventKey<T>(); |
|
|
|
|
|
return DoFindSubscriptionToRemove(eventName, typeof(TH)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private SubscriptionInfo DoFindSubscriptionToRemove(string eventName, Type handlerType) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!HasSubscriptionsForEvent(eventName)) |
|
|
|
|
|
{ |
|
|
|
|
|
return null; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return _handlers[eventName].SingleOrDefault(s => s.HandlerType == handlerType); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public bool HasSubscriptionsForEvent<T>() where T : IntegrationEvent |
|
|
|
|
|
{ |
|
|
|
|
|
var key = GetEventKey<T>(); |
|
|
|
|
|
return HasSubscriptionsForEvent(key); |
|
|
|
|
|
} |
|
|
|
|
|
public bool HasSubscriptionsForEvent(string eventName) => _handlers.ContainsKey(eventName); |
|
|
|
|
|
|
|
|
|
|
|
public Type GetEventTypeByName(string eventName) => _eventTypes.SingleOrDefault(t => t.Name == eventName); |
|
|
|
|
|
|
|
|
|
|
|
public string GetEventKey<T>() |
|
|
|
|
|
{ |
|
|
|
|
|
return typeof(T).Name; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public partial class InMemoryEventBusSubscriptionsManager : IEventBusSubscriptionsManager |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private readonly Dictionary<string, List<SubscriptionInfo>> _handlers; |
|
|
|
|
|
private readonly List<Type> _eventTypes; |
|
|
|
|
|
|
|
|
|
|
|
public event EventHandler<string> OnEventRemoved; |
|
|
|
|
|
|
|
|
|
|
|
public InMemoryEventBusSubscriptionsManager() |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers = new Dictionary<string, List<SubscriptionInfo>>(); |
|
|
|
|
|
_eventTypes = new List<Type>(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public bool IsEmpty => !_handlers.Keys.Any(); |
|
|
|
|
|
public void Clear() => _handlers.Clear(); |
|
|
|
|
|
|
|
|
|
|
|
public void AddDynamicSubscription<TH>(string eventName) |
|
|
|
|
|
where TH : IDynamicIntegrationEventHandler |
|
|
|
|
|
=> DoAddSubscription(typeof(TH), eventName, isDynamic: true); |
|
|
|
|
|
|
|
|
|
|
|
public void AddSubscription<T, TH>() |
|
|
|
|
|
where T : IntegrationEvent |
|
|
|
|
|
where TH : IIntegrationEventHandler<T> |
|
|
|
|
|
{ |
|
|
|
|
|
var eventName = GetEventKey<T>(); |
|
|
|
|
|
DoAddSubscription(typeof(TH), eventName, isDynamic: false); |
|
|
|
|
|
_eventTypes.Add(typeof(T)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void DoAddSubscription(Type handlerType, string eventName, bool isDynamic) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!HasSubscriptionsForEvent(eventName)) |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers.Add(eventName, new List<SubscriptionInfo>()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (_handlers[eventName].Any(s => s.HandlerType == handlerType)) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new ArgumentException( |
|
|
|
|
|
$"Handler Type {handlerType.Name} already registered for '{eventName}'", nameof(handlerType)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (isDynamic) |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers[eventName].Add(SubscriptionInfo.Dynamic(handlerType)); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers[eventName].Add(SubscriptionInfo.Typed(handlerType)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 = FindSubscriptionToRemove<T, TH>(); |
|
|
|
|
|
var eventName = GetEventKey<T>(); |
|
|
|
|
|
DoRemoveHandler(eventName, handlerToRemove); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void DoRemoveHandler(string eventName, SubscriptionInfo subsToRemove) |
|
|
|
|
|
{ |
|
|
|
|
|
if (subsToRemove != null) |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers[eventName].Remove(subsToRemove); |
|
|
|
|
|
if (!_handlers[eventName].Any()) |
|
|
|
|
|
{ |
|
|
|
|
|
_handlers.Remove(eventName); |
|
|
|
|
|
var eventType = _eventTypes.SingleOrDefault(e => e.Name == eventName); |
|
|
|
|
|
if (eventType != null) |
|
|
|
|
|
{ |
|
|
|
|
|
_eventTypes.Remove(eventType); |
|
|
|
|
|
} |
|
|
|
|
|
RaiseOnEventRemoved(eventName); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public IEnumerable<SubscriptionInfo> GetHandlersForEvent<T>() where T : IntegrationEvent |
|
|
|
|
|
=> GetHandlersForEvent(GetEventKey<T>()); |
|
|
|
|
|
public IEnumerable<SubscriptionInfo> GetHandlersForEvent(string eventName) => _handlers[eventName]; |
|
|
|
|
|
|
|
|
|
|
|
private void RaiseOnEventRemoved(string eventName) |
|
|
|
|
|
{ |
|
|
|
|
|
var handler = OnEventRemoved; |
|
|
|
|
|
if (handler != null) |
|
|
|
|
|
{ |
|
|
|
|
|
OnEventRemoved(this, eventName); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private SubscriptionInfo FindDynamicSubscriptionToRemove<TH>(string eventName) |
|
|
|
|
|
where TH : IDynamicIntegrationEventHandler |
|
|
|
|
|
=> DoFindSubscriptionToRemove(eventName, typeof(TH)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private SubscriptionInfo FindSubscriptionToRemove<T, TH>() |
|
|
|
|
|
where T : IntegrationEvent |
|
|
|
|
|
where TH : IIntegrationEventHandler<T> |
|
|
|
|
|
=> DoFindSubscriptionToRemove(GetEventKey<T>(), typeof(TH)); |
|
|
|
|
|
|
|
|
|
|
|
private SubscriptionInfo DoFindSubscriptionToRemove(string eventName, Type handlerType) |
|
|
|
|
|
=> !HasSubscriptionsForEvent(eventName) ? null : _handlers[eventName].SingleOrDefault(s => s.HandlerType == handlerType); |
|
|
|
|
|
|
|
|
|
|
|
public bool HasSubscriptionsForEvent<T>() where T : IntegrationEvent |
|
|
|
|
|
=> HasSubscriptionsForEvent(GetEventKey<T>()); |
|
|
|
|
|
public bool HasSubscriptionsForEvent(string eventName) => _handlers.ContainsKey(eventName); |
|
|
|
|
|
|
|
|
|
|
|
public Type GetEventTypeByName(string eventName) => _eventTypes.SingleOrDefault(t => t.Name == eventName); |
|
|
|
|
|
|
|
|
|
|
|
public string GetEventKey<T>() |
|
|
|
|
|
=> typeof(T).Name; |
|
|
|
|
|
} |
|
|
} |
|
|
} |