我已经被一个问题困扰了一段时间。我正在构建一个基于 eShopOnContainers GitHub 项目 See Here 的项目。我的项目正在 asp.net core 2.2 上运行,我正在使用
MediatR 6.0,
- MediatR 6.0
- MediatR.Extensions.Microsoft.DependencyInjection 6.0.1
- FluentValidation.AspNetCore 8.1.2
- Autofac.Extensions.DependencyInjection 4.3.1
我正在使用由命令处理程序处理的 MediatR 命令,通过许多文章以及在线 eShopOnContainers 示例,我已经实现了 ValidatorBehavior
实现 IPipelineBehavior
的类.
public class ValidatorBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidatorBehavior(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var context = new ValidationContext(request);
var failures = _validators
.Select(v => v.Validate(context))
.SelectMany(result => result.Errors)
.Where(error => error != null)
.ToList();
if (failures.Any())
{
throw new PlanningDomainException(
$"Command Validation Errors for type {typeof(TRequest).Name}", new ValidationException("Validation exception", failures));
}
var response = await next();
return response;
}
}
我还包含了一个 MediatorModule,就像在示例项目中实现的那样。
public class MediatorModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(IMediator).GetType().Assembly)
.AsImplementedInterfaces();
// Get the assembly name
var assembly = typeof(Startup).GetType().Assembly;
// Register all the Command classes (they implement IRequestHandler) in assembly holding the Commands
builder.RegisterAssemblyTypes(assembly)
.AsClosedTypesOf(typeof(IRequestHandler<,>));
// Register the DomainEventHandler classes (they implement INotificationHandler<>)
// in assembly holding the Domain Events
builder.RegisterAssemblyTypes(assembly)
.AsClosedTypesOf(typeof(INotificationHandler<>));
// Register the Command's Validators (Validators based on FluentValidation library)
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.IsClosedTypeOf(typeof(IValidator<>)))
.AsImplementedInterfaces();
builder.Register<ServiceFactory>(context =>
{
var componentContext = context.Resolve<IComponentContext>();
return t => { object o; return componentContext.TryResolve(t, out o) ? o : null; };
});
builder.RegisterGeneric(typeof(LoggingBehavior<,>)).As(typeof(IPipelineBehavior<,>));
builder.RegisterGeneric(typeof(ValidatorBehavior<,>)).As(typeof(IPipelineBehavior<,>));
builder.RegisterGeneric(typeof(TransactionBehaviour<,>)).As(typeof(IPipelineBehavior<,>));
}
}
我的测试 Controller 是:
[Route("api/[controller]")]
[ApiController]
public class ApplicationsController : ControllerBase
{
private readonly IMediator _mediator;
public ApplicationsController(IMediator mediator)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
}
[HttpPost]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> Put([FromBody]ApplicationCreateCommand command, [FromHeader(Name = "x-requestid")] string requestId)
{
var c = await _mediator.Send(command);
return c ? Ok() : (IActionResult)BadRequest();
}
}
我有以下问题:
每当我尝试调用此 API 时,都会收到以下错误:
无法解析构造函数“Void .ctor(MediatR.IMediator)”的参数“MediatR.IMediator mediator”。
我通过使用.AddMediatR()
添加中介作为服务来解决这个问题即使在示例项目中它从未像这样添加。
- 添加 mediatr 后,API 就会正确运行,并且正在发送命令,并且处理的命令正在正确处理。同时,
ValidatorBehavior
正在正确调用,但 CommandValidator 不存在。_validators
列表实际上是空的,因此没有进行任何验证。
我还在命令验证器中设置了断点,但没有被击中。
这是我的命令验证器:
public class ApplicationCreateCommandValidator : AbstractValidator<ApplicationCreateCommand>
{
public ApplicationCreateCommandValidator()
{
RuleFor(cmd => cmd.CategoryType).NotEmpty().Must(BeValidCategoryType).WithMessage("The category type is not valid.");
RuleFor(cmd => cmd.CompetitionId).NotEmpty().WithMessage("The competition id must be specified.");
RuleFor(cmd => cmd.ParticipantId).NotEmpty().WithMessage("The participant id must be specified.");
}
private bool BeValidCategoryType(int categoryType)
{
return categoryType != 0;
}
}
一切都应该正常!我不明白为什么它不会。也许我没有在 autofac 中正确加载命令验证器,但是,我在网上找到的每个示例代码都指向相同的注册方法:
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.IsClosedTypeOf(typeof(IValidator<>)))
.AsImplementedInterfaces();
如果您想仔细查看,我的 git hub 帐户上有该项目的完整源代码。 This is the API 。
任何人都可以帮助我理解我做错了什么吗?这几天我都快疯了。
最佳答案
我的配置和你的差不多。我能找到的唯一区别是 start.cs 文件中的以下几行
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddFluentValidation(fv =>
{
fv.RegisterValidatorsFromAssemblyContaining<MediatorModule>();
fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
}
);
}
关于c# - FluentValidation 命令验证器未由 AutoFac 注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54272950/