在Biwen.QuickApi中实现了一个极简的事件总线,代码简单易懂,对初学者可能有一定帮助。以下是相关代码,欢迎交流和提出改进建议。
首先,我们定义了一个事件约定的空接口:
public interface IEvent{}
接着定义了事件订阅者接口:
public interface IEventSubscriber<T> where T : IEvent
{
Task HandleAsync(T @event, CancellationToken ct);
int Order { get; }
bool ThrowIfError { get; }
}
public abstract class EventSubscriber<T> : IEventSubscriber<T> where T : IEvent
{
public abstract Task HandleAsync(T @event, CancellationToken ct);
public virtual int Order => 0;
public virtual bool ThrowIfError => false;
}
接下来是发布者的实现:
internal class Publisher(IServiceProvider serviceProvider)
{
public async Task PublishAsync<T>(T @event, CancellationToken ct) where T : IEvent
{
var handlers = serviceProvider.GetServices<IEventSubscriber<T>>();
if (handlers is null) return;
foreach (var handler in handlers.OrderBy(x => x.Order))
{
try
{
await handler.HandleAsync(@event, ct);
}
catch
{
if (handler.ThrowIfError)
{
throw;
}
//todo:
}
}
}
}
发布订阅的基本代码编写完成后,接下来是注册发布者和所有的订阅者。核心代码如下:
static readonly Type InterfaceEventSubscriber = typeof(IEventSubscriber<>);
static readonly object _lock = new();//锁
//注册EventSubscribers
foreach (var handlerType in EventHandlers)
{
var baseType = handlerType.GetInterfaces().First(x => x.IsGenericType && x.GetGenericTypeDefinition() == InterfaceEventSubscriber);
services.AddScoped(baseType, handlerType);
}
//注册Publisher
services.AddScoped<Publisher>();
随后,我们将发布订阅封装到QuickApi中使用:
internal interface IPublisher
{
Task PublishAsync<T>(T @event, CancellationToken cancellationToken) where T : IEvent;
}
然后BaseQuickApi实现IPublisher接口:
internal interface IQuickApi<Req, Rsp> : IHandlerBuilder, IQuickApiMiddlewareHandler, IAntiforgeryApi, IPublisher
{
ValueTask<Rsp> ExecuteAsync(Req request);
}
// BaseQuickApi.PublishAsync
public virtual async Task PublishAsync<T>(T @event, CancellationToken cancellationToken = default) where T : IEvent
{
using var scope = ServiceRegistration.ServiceProvider.CreateScope();
var publisher = scope.ServiceProvider.GetRequiredService<Publisher>();
await publisher.PublishAsync(@event, cancellationToken);
}
所有功能完成后,我们进行了简单的测试:
using Biwen.QuickApi.Events;
using Microsoft.AspNetCore.Mvc;
namespace Biwen.QuickApi.DemoWeb.Apis
{
// 代码略
}
最后,我们运行项目进行测试:
curl -X 'GET' 'http://localhost:5101/quick/event?Message=hello%20world' -H 'accept: */*'
源代码已发布到GitHub,欢迎star!
GitHub链接