将验证添加到MediatR行为管道? [英] Add validation to a MediatR behavior pipeline?

查看:384
本文介绍了将验证添加到MediatR行为管道?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用内置容器ASP.NET Core和支持的MediatR 3. 行为"管道:

I'm using ASP.NET Core, the built-in container, and MediatR 3 which supports "behavior" pipelines:

public class MyRequest : IRequest<string>
{
    // ...
}

public class MyRequestHandler : IRequestHandler<MyRequest, string>
{
    public string Handle(MyRequest message)
    {
        return "Hello!";
    }
}

public class MyPipeline<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next)
    {
        var response = await next();
        return response;
    }
}

// in `Startup.ConfigureServices()`:
services.AddTransient(typeof(IPipelineBehavior<MyRequest,str‌​ing>), typeof(MyPipeline<MyRequest,string>))

我在管道中需要一个FluentValidation验证器.在MediatR 2中,因此创建了验证管道:

I need a FluentValidation validator in the pipeline. In MediatR 2, a validation pipeline was created thus:

public class ValidationPipeline<TRequest, TResponse>
    : IRequestHandler<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{

    public ValidationPipeline(IRequestHandler<TRequest, TResponse> inner, IEnumerable<IValidator<TRequest>> validators)
    {
        _inner = inner;
        _validators = validators;
    }

    public TResponse Handle(TRequest message)
    {
        var failures = _validators
            .Select(v => v.Validate(message))
            .SelectMany(result => result.Errors)
            .Where(f => f != null)
            .ToList();
        if (failures.Any())
            throw new ValidationException(failures);
        return _inner.Handle(request);
    }

}

现在如何为新版本执行此操作?如何设置要使用的验证器?

How do I do that now for the new version? How do I set which validator to use?

推荐答案

过程完全相同,只需更改接口即可使用新的IPipelineBehavior<TRequest, TResponse>接口.

The process is exactly the same, you just have to change the interface to use the new IPipelineBehavior<TRequest, TResponse> interface.

public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    private readonly IEnumerable<IValidator<TRequest>> _validators;

    public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
    {
        _validators = validators;
    }

    public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next)
    {
        var context = new ValidationContext(request);
        var failures = _validators
            .Select(v => v.Validate(context))
            .SelectMany(result => result.Errors)
            .Where(f => f != null)
            .ToList();

        if (failures.Count != 0)
        {
            throw new ValidationException(failures);
        }

        return next();
    }
}

对于验证器,您应该在内置容器中将所有验证器注册为IValidator<TRequest>,以便将其注入到行为中.如果您不想一个接一个地注册它们,建议您查看一个很棒的 Scrutor库具有程序集扫描功能.这样,它将找到您自己的验证器.

For the validators, you should register all the validators as IValidator<TRequest> in the built-in container so they'll be injected in the behavior. If you don't want to register them one by one, I suggest that you have a look at the great Scrutor library that brings assembly scanning capabilities. This way it'll find your validators itself.

此外,在新系统中,您不再使用装饰器模式,只需在容器中注册常规行为,MediatR便会自动将其拾取.看起来可能像这样:

Also, with the new system, you don't use the decorator pattern anymore, you just register your generic behavior in the container and MediatR will pick it up automatically. It could look something like:

var services = new ServiceCollection();
services.AddMediatR(typeof(Program));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
var provider = services.BuildServiceProvider();

这篇关于将验证添加到MediatR行为管道?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆