4

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)検証を行わずに直接入ります。

4

1 に答える 1

1

問題は次の行にあります。

typeof(IRequestHandler<,>), fromKey: "handler", toKey: "Validator")

handlerキーが見つかりません。
そのため、最初にすべての型をアセンブリに登録し、RequestHandlers を除外して、型の登録を分割しました。そして、RequestHandlers を key で登録しましたhandler

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

お役に立てれば!

于 2016-09-11T14:40:42.400 に答える