68 lines
3.1 KiB
C#
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);
|
|
}
|
|
|
|
|
|
}
|