将validation添加到MediatR行为管道?

我正在使用内置容器ASP.NET Core和支持“行为”管道的 MediatR 3:

public class MyRequest : IRequest { // ... } public class MyRequestHandler : IRequestHandler { public string Handle(MyRequest message) { return "Hello!"; } } public class MyPipeline : IPipelineBehavior { public async Task Handle(TRequest request, RequestHandlerDelegate next) { var response = await next(); return response; } } // in `Startup.ConfigureServices()`: services.AddTransient(typeof(IPipelineBehavior), typeof(MyPipeline)) 

我需要在管道中使用FluentValidationvalidation器。 在MediatR 2中, 创建了一个validation管道 :

 public class ValidationPipeline : IRequestHandler where TRequest : IRequest { public ValidationPipeline(IRequestHandler inner, IEnumerable<IValidator> validators) { _inner = inner; _validators = validators; } public TResponse Handle(TRequest message) { var failures = _validators .Select(v => v.Validate(message)) .SelectMany(result => result.Errors) .Where(f => f != null) .ToList(); if (failures.Any()) throw new ValidationException(failures); return _inner.Handle(request); } } 

我现在如何为新版本做到这一点? 如何设置要使用的validation器?

过程完全相同,您只需更改界面即可使用新的IPipelineBehavior界面。

 public class ValidationBehavior : IPipelineBehavior where TRequest : IRequest { private readonly IEnumerable> _validators; public ValidationBehavior(IEnumerable> validators) { _validators = validators; } public Task Handle(TRequest request, RequestHandlerDelegate next) { var context = new ValidationContext(request); var failures = _validators .Select(v => v.Validate(context)) .SelectMany(result => result.Errors) .Where(f => f != null) .ToList(); if (failures.Count != 0) { throw new ValidationException(failures); } return next(); } } 

对于validation器,您应该在内置容器IValidator所有validation器注册为IValidator ,以便将它们注入到行为中。 如果您不想逐个注册它们,我建议您查看带有程序集扫描function的优秀Scrutor库 。 这样它就可以找到你的validation器。

此外,使用新系统,您不再使用装饰器模式,只需在容器中注册通用行为,MediatR将自动选择它。 它可能看起来像:

 var services = new ServiceCollection(); services.AddMediatR(typeof(Program)); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); var provider = services.BuildServiceProvider();