使用一个Validator进行多个请求DTO?或单个请求DTO的多个验证器?

时间:2013-05-24 21:59:23

标签: servicestack fluentvalidation

我有几个ServiceStack请求DTO,它们实现了一个名为IPageable的接口。我有一个验证器,可以验证此接口上的两个属性。我想我最终会为每个请求类型设置一个验证器,但我试图避免在所有这些验证逻辑中复制与IPageable相关的验证逻辑。

public class PageableValidator : AbstractValidator<IPageable>
{
    public PageableValidator()
    {
        RuleFor(req => req.Page)
            .GreaterThanOrEqualTo(1);
        RuleFor(req => req.PageSize)
            .GreaterThanOrEqualTo(1)
            .When(req => req.Page > 1);
    }
}

我对此有一些想法包括:

  1. 看来我不能只使用container.RegisterValidators() 对于所有实现IPageable的请求类型,这是我的 首先想到的。

  2. 我可以在所有请求中指定多个<Validator>属性 定义,以便特定于请求的验证器也运行 作为我的IPageable验证器?

  3. 我可以在验证器注册时指定所有类型 实现IPageable,我的IPageable验证器应该运行吗?

  4. 我可以为我的特定于请求的验证器编写基类吗? 从我的PageableValidator获取规则并包含/运行它们?

  5. 我可以通过继承AbstractValidator<T> where T : IPageable来做一些工作,但我希望能够以更多面向方面的方式对多个接口进行验证。

1 个答案:

答案 0 :(得分:2)

我不知道你问题的答案,但在阅读你的问题之后会想到一些选择。

我不熟悉<Validator>属性,但就问题2而言,您可以创建一个Filter attribute来运行您的分页验证。这允许您在请求中使用许多属性并设置其优先级。

public class PageableValidator : Attribute, IHasRequestFilter
{
    public void RequestFilter(IHttpRequest req, IHttpResponse res, object requestDto)
    {
        if (requestDto is IPageable)
        {
            var validator = new PageableValidator(); //could use IOC for this
            validator.ValidateAndThrow(requestDto as IPageable);
        }

    }

    public IHasRequestFilter Copy()
    {
        return (IHasRequestFilter)this.MemberwiseClone();
    }

    public int Priority { get { return -1; //setting to negative value to run it before any other filters} }
}

另一种选择是为分页验证创建一个抽象类。这将需要每个请求的子类,并需要更多的代码和一些重复*。但是,根据您希望如何处理错误消息,您可以移动代码。

public abstract class PagerValidatorBase<T> : AbstractValidator<T>
{
    public bool ValidatePage(IPageable instance, int page)
    {
        if (page >= 1)
            return true;

        return false;
    }

    public bool ValidatePageSize(IPageable instance, int pageSize)
    {
        if (pageSize >= 1 && instance.Page > 1)
            return true;

        return false;
    }
}

public class SomeRequestValidator : PagerValidatorBase<SomeRequest>
{
    public SomeRequestValidator()
    {
        //validation rules for SomeRequest
        RuleFor(req => req.Page).Must(ValidatePage);
        RuleFor(req => req.PageSize).Must(ValidatePageSize);
    }
}
  • IMO,重复使代码更加明确(不是坏事)并且没有问题,因为它没有重复逻辑。