using Serilog; using System; using System.Collections.Concurrent; using Wood.EventBus.Events; using Wood.Util; namespace Wood.EventBus { public class InMemoryEventBus : IEventBus { private readonly ConcurrentDictionary> _handlersMap = new(); public void Subscribe(TH handler) where T : IntegrationEvent where TH : IIntegrationEventHandler { var eventName = typeof(T).Name; if (!_handlersMap.TryGetValue(eventName, out var handlers)) { handlers = new List(); _handlersMap.TryAdd(eventName, handlers); } handlers.Add(handler); } public void Unsubscribe() where T : IntegrationEvent where TH : IIntegrationEventHandler { var eventName = typeof(T).Name; if (_handlersMap.TryGetValue(eventName, out var handlers)) { handlers.RemoveAll(h => h is TH); } } public async Task PublishAsync(T @event) where T : IntegrationEvent { var eventName = typeof(T).Name; if (_handlersMap.TryGetValue(eventName, out var handlers)) { foreach (var handler in handlers) { var methodInfo = handler.GetType().GetMethods().FirstOrDefault(m => m.Name == "Handle" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(T)); if (methodInfo != null) { await (Task)methodInfo.Invoke(handler, new object[] { @event })!; } } } } public void Publish(T @event) where T : IntegrationEvent { var eventName = typeof(T).Name; if (_handlersMap.TryGetValue(eventName, out var handlers)) { foreach (var handler in handlers) { var methodInfo = handler.GetType().GetMethods().FirstOrDefault(m => m.Name == "Handle" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(T)); if (methodInfo != null) { methodInfo.Invoke(handler, new object[] { @event }); } } } } } }