MASA Framework -- EventBus入门与设计( 二 )


自定义中间件根据需要我们可以自定义中间件,并注册到EventBus的请求管道中,比如通过增加FluentValidation, 将参数验证从业务代码中剥离开来,从而使得处理程序更专注于业务

  1. 注册FluentValidation, 修改Program.cs
builder.Services.AddValidatorsFromAssembly(Assembly.GetEntryAssembly());
  1. 自定义验证中间件ValidatorMiddleware.cs , 用于验证参数
public class ValidatorMiddleware<TEvent> : Middleware<TEvent>    where TEvent : IEvent{    private readonly ILogger<ValidatorMiddleware<TEvent>>? _logger;    private readonly IEnumerable<IValidator<TEvent>> _validators;    public ValidatorMiddleware(IEnumerable<IValidator<TEvent>> validators, ILogger<ValidatorMiddleware<TEvent>>? logger = null)    {        _validators = validators;        _logger = logger;    }    public override async Task HandleAsync(TEvent @event, EventHandlerDelegate next)    {        var typeName = @event.GetType().FullName;        _logger?.LogDebug("----- Validating command {CommandType}", typeName);        var failures = _validators            .Select(v => v.Validate(@event))            .SelectMany(result => result.Errors)            .Where(error => error != null)            .ToList();        if (failures.Any())        {            _logger?.LogError("Validation errors - {CommandType} - Event: {@Command} - Errors: {@ValidationErrors}",                typeName,                @event,                failures);            throw new ValidationException("Validation exception", failures);        }        await next();    }}
  1. 注册EventBus并使用验证中间件ValidatorMiddleware
builder.Services.AddEventBus(eventBusBuilder=>eventBusBuilder.UseMiddleware(typeof(ValidatorMiddleware<>)));
  1. 添加注册用户验证类RegisterUserEventValidator.cs
public class RegisterUserEventValidator : AbstractValidator<RegisterUserEvent>{    public RegisterUserEventValidator()    {        RuleFor(e => e.Account).NotNull().WithMessage("用户名不能为空");        RuleFor(e => e.Email).NotNull().WithMessage("邮箱不能为空");        RuleFor(e => e.Password)            .NotNull().WithMessage("密码不能为空")            .MinimumLength(6)            .WithMessage("密码必须大于6位")            .MaximumLength(20)            .WithMessage("密码必须小于20位");    }}编排EventBus 支持事件编排,它们可以用来处理一些对执行顺序有要求的业务,比如: 注册用户必须成功之后才可以发送注册邮件通知,发送奖励等等,那我们可以这样做
将注册用户业务拆分为三个Handler,并通过指定Order的值来对执行事件排序
public class UserHandler{    private readonly ILogger<UserHandler>? _logger;    public UserHandler(ILogger<UserHandler>? logger = null)    {        _logger = logger;    }    [EventHandler(1)]    public void RegisterUser(RegisterUserEvent @event)    {        _logger?.LogDebug("-----------{Message}-----------", "检测用户是否存在并注册用户");        //todo: 编写注册用户业务    }    [EventHandler(2)]    public void SendAwardByRegister(RegisterUserEvent @event)    {        _logger?.LogDebug("-----------{Account} 注册成功 {Message}-----------", @event.Account, "发送注册奖励");        //todo: 编写发送奖励等    }    [EventHandler(3)]    public void SendNoticeByRegister(RegisterUserEvent @event)    {        _logger?.LogDebug("-----------{Account} 注册成功 {Message}-----------", @event.Account, "发送注册成功邮件");        //todo: 编写发送注册通知等    }}

推荐阅读