Files
Store.Management/Source/Core/MAX.Notification/NotificationPublisher.cs
T
2026-10-27 14:35:03 +08:00

68 lines
3.1 KiB
C#

// 摘自 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<Type, NotificationHandlerWrapper> _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>(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)}")
};
/// <summary>
/// 在派生类中重写此方法可控制任务的等待方式。默认调用 <see cref="INotificationPublisher"/>。
/// </summary>
/// <param name="handlerExecutors">封装各通知处理器实例及其调用委托的执行器集合。</param>
/// <param name="notification">要发布的通知。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>表示本次处理器分发操作的任务。</returns>
protected virtual Task PublishCore(IEnumerable<NotificationHandlerExecutor> 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);
}
}