using ZeroFramework.EventBus.Abstractions; using ZeroFramework.EventBus.Events; namespace ZeroFramework.EventBus { public partial class InMemoryEventBusSubscriptionsManager : IEventBusSubscriptionsManager { private readonly Dictionary> _handlers; private readonly List _eventTypes; public event EventHandler? OnEventRemoved; public InMemoryEventBusSubscriptionsManager() { _handlers = []; _eventTypes = []; } public bool IsEmpty => !_handlers.Keys.Any(); public void Clear() => _handlers.Clear(); public void AddDynamicSubscription(string eventName) where TH : IDynamicIntegrationEventHandler { DoAddSubscription(typeof(TH), eventName, isDynamic: true); } public void AddSubscription() where T : IntegrationEvent where TH : IIntegrationEventHandler { var eventName = GetEventKey(); DoAddSubscription(typeof(TH), eventName, isDynamic: false); if (!_eventTypes.Contains(typeof(T))) { _eventTypes.Add(typeof(T)); } } private void DoAddSubscription(Type handlerType, string eventName, bool isDynamic) { if (!HasSubscriptionsForEvent(eventName)) { _handlers.Add(eventName, []); } 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(string eventName) where TH : IDynamicIntegrationEventHandler { var handlerToRemove = FindDynamicSubscriptionToRemove(eventName); if (handlerToRemove is not null) { DoRemoveHandler(eventName, handlerToRemove); } } public void RemoveSubscription() where TH : IIntegrationEventHandler where T : IntegrationEvent { var handlerToRemove = FindSubscriptionToRemove(); var eventName = GetEventKey(); if (handlerToRemove is not null) { 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 GetHandlersForEvent() where T : IntegrationEvent { var key = GetEventKey(); return GetHandlersForEvent(key); } public IEnumerable GetHandlersForEvent(string eventName) => _handlers[eventName]; private void RaiseOnEventRemoved(string eventName) { var handler = OnEventRemoved; handler?.Invoke(this, eventName); } private SubscriptionInfo? FindDynamicSubscriptionToRemove(string eventName) where TH : IDynamicIntegrationEventHandler { return DoFindSubscriptionToRemove(eventName, typeof(TH)); } private SubscriptionInfo? FindSubscriptionToRemove() where T : IntegrationEvent where TH : IIntegrationEventHandler { var eventName = GetEventKey(); return DoFindSubscriptionToRemove(eventName, typeof(TH)); } private SubscriptionInfo? DoFindSubscriptionToRemove(string eventName, Type handlerType) { if (HasSubscriptionsForEvent(eventName)) { return _handlers[eventName].Single(s => s.HandlerType == handlerType); } return null; } public bool HasSubscriptionsForEvent() where T : IntegrationEvent { var key = GetEventKey(); return HasSubscriptionsForEvent(key); } public bool HasSubscriptionsForEvent(string eventName) => _handlers.ContainsKey(eventName); public Type GetEventTypeByName(string eventName) => _eventTypes.Single(t => t.Name == eventName); public string GetEventKey() => typeof(T).Name; } }