// 摘自 MediatR 14.2.0 的 Mediator.cs,仅保留通知功能。 // 许可声明与修改记录见 LICENSE.md 和 UPSTREAM.md。 using System.Collections.Concurrent; using MAX.Notification.NotificationPublishers; using MAX.Notification.Wrappers; namespace MAX.Notification; public class NotificationPublisher : IPublisher { private readonly IServiceProvider _serviceProvider; private readonly INotificationPublisher _publisher; private static readonly ConcurrentDictionary _notificationHandlers = new(); public NotificationPublisher(IServiceProvider serviceProvider) : this(serviceProvider, new ForeachAwaitPublisher()) { } public NotificationPublisher(IServiceProvider serviceProvider, INotificationPublisher publisher) { ArgumentNullException.ThrowIfNull(serviceProvider); ArgumentNullException.ThrowIfNull(publisher); _serviceProvider = serviceProvider; _publisher = publisher; } public Task Publish(TNotification notification, CancellationToken cancellationToken = default) where TNotification : INotification { if (notification == null) { throw new ArgumentNullException(nameof(notification)); } return PublishNotification(notification, cancellationToken); } public Task Publish(object notification, CancellationToken cancellationToken = default) => notification switch { null => throw new ArgumentNullException(nameof(notification)), INotification instance => PublishNotification(instance, cancellationToken), _ => throw new ArgumentException($"{nameof(notification)} does not implement ${nameof(INotification)}") }; /// /// 在派生类中重写此方法可控制任务的等待方式。默认调用 。 /// /// 封装各通知处理器实例及其调用委托的执行器集合。 /// 要发布的通知。 /// 取消令牌。 /// 表示本次处理器分发操作的任务。 protected virtual Task PublishCore(IEnumerable handlerExecutors, INotification notification, CancellationToken cancellationToken) => _publisher.Publish(handlerExecutors, notification, cancellationToken); private Task PublishNotification(INotification notification, CancellationToken cancellationToken = default) { var handler = _notificationHandlers.GetOrAdd(notification.GetType(), static notificationType => { var wrapperType = typeof(NotificationHandlerWrapperImpl<>).MakeGenericType(notificationType); var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($"Could not create wrapper for type {notificationType}"); return (NotificationHandlerWrapper)wrapper; }); return handler.Handle(notification, _serviceProvider, PublishCore, cancellationToken); } }