我正在尝试使用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)
中进行验证。
答案 0 :(得分:1)
问题出在这一行:
typeof(IRequestHandler<,>), fromKey: "handler", toKey: "Validator")
找不到handler
键
因此,我首先注册程序集中的所有类型但不包括RequestHandlers,从而拆分类型的注册。然后使用密钥handler
注册RequestHandlers。
public IServiceProvider ConfigureServices(IServiceCollection services)
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof(GetUserByEmailQuery).GetTypeInfo().Assembly)
.Where(t => !t.IsClosedTypeOf(typeof(IRequestHandler<,>)))
.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.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.As(type => type.GetInterfaces()
.Where(interfaceType => interfaceType.IsClosedTypeOf(typeof(IRequestHandler<,>)))
.Select(interfaceType => new KeyedService("handler", interfaceType)))
.InstancePerLifetimeScope();
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>();
}
希望这有帮助!