У меня есть поведение конвейера MediatR, подобное этому:
public class FailFastRequestBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly IEnumerable<IValidator> _validators;
public FailFastRequestBehavior(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var failures = _validators
.Select(async v => await v.ValidateAsync(request))
.SelectMany(result => result.Result.Errors)
.Where(f => f != null);
return failures.Any()
? Errors(failures)
: next();
}
...
}
И команды MediatR, такие как:
public class MyUseCase
{
public class Command : IRequest<CommandResponse>
{
...
}
public class Validator : AbstractValidator<Command>
{
...
}
public class Handler<T>: IRequestHandler<T, CommandResponse>
{
...
}
}
Валидаторы зарегистрированы на Startup.cs
следующим образом:
AssemblyScanner
.FindValidatorsInAssembly(Assembly.GetAssembly(typeof(MyUseCase)))
.ForEach(result =>
services.AddScoped(result.InterfaceType, result.ValidatorType));
Это хорошо работает для MyUseCase.Validator
, оно внедряется в конвейер и выполняется, проверяя MyUseCase.Command
.
Но это большое приложение, и многие команды имеют общие свойства,то есть каждая операция заказа получает OrderId
, и я должен проверить, является ли идентификатор действительным, существует ли сущность в базе данных, является ли аутентифицированный пользователь владельцем изменяемого заказа и т. д.
Итак, япопытался создать следующий интерфейс и валидатор:
public interface IOrder
{
string OrderId { get; set; }
}
public class IOrderValidator : AbstractValidator<IOrder>
{
public IOrderValidator()
{
CascadeMode = CascadeMode.StopOnFirstFailure;
RuleFor(x => x.OrderId)
.Rule1()
.Rule2()
.Rule3()
.RuleN()
}
}
Наконец я изменил команду на эту:
public class MyUseCase
{
public class Command : IRequest<CommandResponse>: IOrder
{
...
}
public class Validator : AbstractValidator<Command>
{
...
}
public class Handler<T>: IRequestHandler<T, CommandResponse>
{
...
}
}
Проблема в том, что IOrderValidator
не вводится в конвейер,только MyUseCase.Validator
- это.
Я что-то здесь упускаю или вообще возможно добавить несколько валидаторов в конвейер?