FluentValidation装饰器不能与autofac和mediator一起使用

时间:2016-07-09 09:03:18

标签: asp.net-core autofac cqrs fluentvalidation mediatr

我正在尝试使用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)中进行验证。

1 个答案:

答案 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>();
}

希望这有帮助!