using Microsoft.Extensions.DependencyInjection; using System.Reflection; namespace Toolkit.Foundation; public class Mediator(IHandlerProvider handlerProvider, IServiceProvider provider) : IMediator { public async Task Handle(TMessage message, CancellationToken cancellationToken = default) where TMessage : notnull { Type messageType = message.GetType(); Type handlerWrapperType = typeof(HandlerWrapper<,>).MakeGenericType(messageType, typeof(TResponse)); Dictionary> handlers = []; foreach (object? service in provider.GetServices(handlerWrapperType)) { if (service?.GetType() is Type serviceType) { if (!handlers.TryGetValue(serviceType, out List? handlerList)) { handlerList = []; handlers.Add(serviceType, handlerList); } handlerList.Add(service); } } foreach (object? handler in handlerProvider.Get(messageType)) { if (handler is not null) { Type handlerType = handler.GetType(); if (!handlers.TryGetValue(handlerType, out List? handlerList)) { handlerList = []; handlers.Add(handlerType, handlerList); } handlerList.Add(handler); } } foreach (KeyValuePair> handlerEntry in handlers) { foreach (object? handler in handlerEntry.Value) { if (handler?.GetType().GetMethod("Handle", [messageType, typeof(CancellationToken)]) is MethodInfo handleMethod) { return await (Task)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!; } } } return default; } public Task Handle(object message, CancellationToken cancellationToken = default) { if (message.GetType().GetInterface(message.GetType().Name) is Type requestType && requestType.GetGenericArguments().Length == 1) { Type responseType = requestType.GetGenericArguments()[0]; Type handlerType = typeof(HandlerWrapper<,>).MakeGenericType(message.GetType(), responseType); if (provider.GetService(handlerType) is object handler) { if (handlerType.GetMethod("Handle") is MethodInfo handleMethod) { return (Task)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!; } } } return Task.FromResult(default); } }