CQRS パターンを使用して ASP.NET Core アプリケーションをセットアップしようとしています。これを達成するために、私はこれらのライブラリを使用しています:
"Autofac.Extensions.DependencyInjection": "4.0.0-rc3-280",
"FluentValidation": "6.4.0-beta3",
"MediatR": "2.1.0"
必要な設定をすべて実行し、Mediatr が機能し、依存性注入が機能しましたが、コードはハンドラーに行く前に検証を通過しません。検証デコレータの登録に問題があると思います。私が使用しているほとんどのライブラリは最近更新され、ASP.NET Core をサポートするために大幅に変更されたためです。構成で何が欠けていますか? それがどうあるべきか?
私の構成
public IServiceProvider ConfigureServices(IServiceCollection services)
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof(GetUserByEmailQuery).GetTypeInfo().Assembly).AsImplementedInterfaces();
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.RegisterGenericDecorator(
typeof(MediatorPipeline<,>),
typeof(IRequestHandler<,>), fromKey: "handler", toKey: "Validator")
.Keyed("MediatorPipeline", typeof(IRequestHandler<,>))
.InstancePerLifetimeScope();
//register validator decorator
builder.RegisterGenericDecorator(
typeof(ValidatorHandler<,>),
typeof(IRequestHandler<,>),
"Validator")
.InstancePerLifetimeScope();
builder.Populate(services);
var container = builder.Build();
return container.Resolve<IServiceProvider>();
}
MediatorPipeline (本当に必要かどうかはわかりません。)
public class MediatorPipeline<TRequest, TResponse> : IRequestHandler<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
private readonly IRequestHandler<TRequest, TResponse> _inner;
private readonly IPreRequestHandler<TRequest>[] _preRequestHandlers;
private readonly IPostRequestHandler<TRequest, TResponse>[] _postRequestHandlers;
public MediatorPipeline(IRequestHandler<TRequest, TResponse> inner, IPreRequestHandler<TRequest>[] preRequestHandlers, IPostRequestHandler<TRequest, TResponse>[] postRequestHandlers)
{
_inner = inner;
_preRequestHandlers = preRequestHandlers;
_postRequestHandlers = postRequestHandlers;
}
public TResponse Handle(TRequest message)
{
foreach (var preRequestHandler in _preRequestHandlers)
{
preRequestHandler.Handle(message);
}
var result = _inner.Handle(message);
foreach (var postRequestHandler in _postRequestHandlers)
{
postRequestHandler.Handle(message, result);
}
return result;
}
}
ValidatorHandler
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)
{
_inner = inner;
_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);
}
}
GetUserByEmailQuery.cs
public class GetUserByEmailQuery : IRequest<UserDomain>
{
public string UserEmail { get; set; }
}
public class GetUserByEmailQueryValidator : AbstractValidator<GetUserByEmailQuery>
{
public GetUserByEmailQueryValidator()
{
RuleFor(q => q.UserEmail).NotNull().WithMessage("Email alanı boş bırakılamaz!");
}
public bool Handle(GetUserByEmailQuery message)
{
return true;
}
}
public class GetUserByEmailQueryHandler : IRequestHandler<GetUserByEmailQuery, UserDomain>
{
private readonly AuthDbContext _context;
public GetUserByEmailQueryHandler(AuthDbContext context)
{
_context = context;
}
public UserDomain Handle(GetUserByEmailQuery message)
{
var authUser = _context.Users.Where(x => x.Email.Equals(message.UserEmail)).Include(y => y.UserMeta).Include(z => z.UserRole).FirstOrDefault();
var userDomain = Mapper.Map<UserDomain>(authUser);
return userDomain;
}
}
このクラスでは、私のコードは public UserDomain Handle(GetUserByEmailQuery message)
検証を行わずに直接入ります。