using System; using System.Collections.Generic; namespace Game.Shared.Events; public sealed class InMemoryEventBus : IEventBus { private readonly Dictionary> _handlers = []; private readonly object _lock = new(); public IDisposable Subscribe(Action handler) where TEvent : IEvent { ArgumentNullException.ThrowIfNull(handler); var eventType = typeof(TEvent); lock (_lock) { if (!_handlers.TryGetValue(eventType, out var list)) { list = []; _handlers[eventType] = list; } list.Add(handler); } return new EventSubscription(() => Unsubscribe(eventType, handler)); } public void Publish(TEvent gameEvent) where TEvent : IEvent { ArgumentNullException.ThrowIfNull(gameEvent); List snapshot = null; var eventType = typeof(TEvent); lock (_lock) { if (_handlers.TryGetValue(eventType, out var list)) { snapshot = new List(list); } } if (snapshot == null) return; foreach (var subscriber in snapshot) { ((Action)subscriber)(gameEvent); } } private void Unsubscribe(Type eventType, Delegate handler) { lock (_lock) { if (!_handlers.TryGetValue(eventType, out var list)) return; list.Remove(handler); if (list.Count == 0) { _handlers.Remove(eventType); } } } public void Clear() { lock (_lock) { _handlers.Clear(); } } private sealed class EventSubscription(Action unsubscribeAction) : IDisposable { private Action _unsubscribeAction = unsubscribeAction; public void Dispose() { _unsubscribeAction?.Invoke(); _unsubscribeAction = null; } } }