Подключение проверки в MediatR и ASP.NET Core с использованием автофака
Я только начал использовать MediatR в основном проекте asp.net и изо всех сил пытаюсь подключить проверку...
Вот мой контроллер:
public class PersonController : Controller
{
IMediator mediator;
public PersonController(IMediator mediator)
{
this.mediator = mediator;
}
[HttpPost]
public async Task<ActionResult> Post([FromBody]CreatePerson model)
{
var success = await mediator.Send(model);
if (success)
{
return Ok();
}
else
{
return BadRequest();
}
}
}
... и команда CreatePerson, проверка (через FluentValidation) и обработчик запроса:
public class CreatePerson : IRequest<bool>
{
public string Title { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
}
public class CreatePersonValidator : AbstractValidator<CreatePerson>
{
public CreatePersonValidator()
{
RuleFor(m => m.FirstName).NotEmpty().Length(1, 50);
RuleFor(m => m.Surname).NotEmpty().Length(3, 50);
}
}
public class CreatePersonHandler : IRequestHandler<CreatePerson, bool>
{
public CreatePersonHandler()
{
}
public bool Handle(CreatePerson message)
{
// do some stuff
return true;
}
}
У меня есть этот общий обработчик проверки:
public class ValidatorHandler<TRequest, TResponse> : IRequestHandler<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
private readonly IRequestHandler<TRequest, TResponse> inner;
private readonly IValidator<TRequest>[] validators;
public ValidatorHandler(IRequestHandler<TRequest, TResponse> inner, IValidator<TRequest>[] validators)
{
this.inner = inner;
this.validators = validators;
}
public TResponse Handle(TRequest message)
{
var context = new ValidationContext(message);
var failures = validators
.Select(v => v.Validate(context))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Any())
throw new ValidationException(failures);
return inner.Handle(message);
}
}
... но я изо всех сил пытаюсь правильно проверить правильность подключения в Startup.ConfigureServices с помощью autofac:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
var builder = new ContainerBuilder();
builder.Register<SingleInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => c.Resolve(t);
});
builder.Register<MultiInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => (IEnumerable<object>)c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
});
builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof(CreatePersonHandler).GetTypeInfo().Assembly).AsClosedTypesOf(typeof(IRequestHandler<,>));
builder.RegisterGenericDecorator(typeof(ValidatorHandler<,>), typeof(IRequestHandler<,>), "Validator").InstancePerLifetimeScope();
builder.Populate(services);
var container = builder.Build();
return container.Resolve<IServiceProvider>();
}
Когда я запускаю приложение и POST /api/person { "title": "Mr", "firstName": "Paul", "фамилия": "" }
Я получаю 200. CreatePersonHandler.Handle() был вызван, но CreatePersonValidator() никогда не вызывается.
Я что-то упустил в Startup.ConfigureServices()?
1 ответ
Предлагаю вам прочитать официальную документацию по подключению декораторов в Autofac.
Декораторы используют именованные сервисы для разрешения декорированных сервисов.
Например, в вашем куске кода:
builder.RegisterGenericDecorator(
typeof(ValidatorHandler<,>),
typeof(IRequestHandler<,>),
"Validator").InstancePerLifetimeScope();
вы указываете Autofac использовать ValidationHandler<,>
в качестве декоратора IRequestHandler<,>
услуги, которые были зарегистрированы с Validator
имя, которое, вероятно, не то, что вы хотите.
Вот как вы можете заставить его работать:
// Register the request handlers as named services
builder
.RegisterAssemblyTypes(typeof(CreatePersonHandler).GetTypeInfo().Assembly)
.AsClosedTypesOf(typeof(IRequestHandler<,>))
.Named("BaseImplementation");
// Register the decorators on top of your request handlers
builder.RegisterGenericDecorator(
typeof(ValidatorHandler<,>),
typeof(IRequestHandler<,>),
fromKey: "BaseImplementation").InstancePerLifetimeScope();
Я нахожу, указав имя fromKey
Параметр помогает понять, как декораторы работают с Autofac.