Добавить проверку к конвейеру поведения MediatR?
Я использую ASP.NET ядро, встроенный контейнер и MediatR 3, который поддерживает "поведенческие" конвейеры :
public class MyRequest : IRequest<string>
{
// ...
}
public class MyRequestHandler : IRequestHandler<MyRequest, string>
{
public string Handle(MyRequest message)
{
return "Hello!";
}
}
public class MyPipeline<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next)
{
var response = await next();
return response;
}
}
// in `Startup.ConfigureServices()`:
services.AddTransient(typeof(IPipelineBehavior<MyRequest,string>), typeof(MyPipeline<MyRequest,string>))
Мне нужен валидатор FluentValidation в конвейере. В MediatR 2 конвейер проверки был создан таким образом:
public class ValidationPipeline<TRequest, TResponse>
: IRequestHandler<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
public ValidationPipeline(IRequestHandler<TRequest, TResponse> inner, IEnumerable<IValidator<TRequest>> 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);
}
}
Как это сделать теперь для новой версии? Как установить, какой валидатор использовать?
1 ответ:
Процесс точно такой же, вам просто нужно изменить интерфейс, чтобы использовать новый интерфейс
IPipelineBehavior<TRequest, TResponse>
.public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse> { private readonly IEnumerable<IValidator<TRequest>> _validators; public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators) { _validators = validators; } public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> 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(); } }
Для валидаторов вы должны зарегистрировать все валидаторы как
IValidator<TRequest>
во встроенном контейнере, чтобы они были введены в поведение. Если вы не хотите регистрировать их по одному, я предлагаю вам взглянуть на большую библиотекуScrutor , которая предоставляет возможности сканирования сборок. Таким образом, он сам найдет ваши валидаторы.Также, с новым система, вы больше не используете шаблон декоратора, вы просто регистрируете свое общее поведение в контейнере, и MediatR автоматически его подберет. Это может выглядеть примерно так:
var services = new ServiceCollection(); services.AddMediatR(typeof(Program)); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); var provider = services.BuildServiceProvider();