【问题标题】:FluentValidation - pre-validation / conditional validation with no code duplicationFluentValidation - 无代码重复的预验证/条件验证
【发布时间】:2018-09-05 08:13:50
【问题描述】:

我正在尝试创建能够有两个组并在第一次失败时阻止第二次验证的验证(它包含许多规则)。

现在我确实在内部创建了一个私有的“BasicValidation”类,并在“主验证器”中这样做:

RuleFor(m => m).SetValidator(new BasicValidation()).DependentRules(() => {
//Complex validation
RuleFor(m => m.IdOfSthInDb)
    .MustAsync(ItemMustExists)
    .WithMessage("Item does not exist.");
});            

它可以解决问题,但我想避免为每个模型创建“BasicValidation”。

【问题讨论】:

    标签: c# .net fluentvalidation


    【解决方案1】:

    在我之前的回答中,我误解了这个问题。主要目标是避免不同验证器中的代码重复。经过一番调查,我找到了符合您要求的解决方案。假设你有模型:

    public abstract class BaseModel
    {
        public string BaseProperty1 { get; set; }
        public string BaseProperty2 { get; set; }
    }
    
    public class ChildModel : BaseModel
    {
        public int IdOfSthInDb { get; set; }
    }
    

    您必须为基本模型创建验证器(它将被进一步使用):

    class InternalBaseModelValidator : AbstractValidator<BaseModel>
    {
        public InternalBaseModelValidator()
        {
            RuleFor(x => x.BaseProperty1).NotEmpty().WithMessage("Property 1 is empty");
            RuleFor(x => x.BaseProperty2).NotEmpty().WithMessage("Property 2 is empty");
        }
    }
    

    然后你就可以使用 FluentValidation 的新功能了,叫做PreValidate:

    public class BaseModelValidator<T>: AbstractValidator<T> where T : BaseModel
    {
        // necessary for reusing base rules
        private readonly InternalBaseModelValidator preValidator; 
    
        protected BaseModelValidator()
        {
            preValidator = new InternalBaseModelValidator();
        }
    
        protected override bool PreValidate(ValidationContext<T> context, ValidationResult result)
        {
            var preValidationResult = preValidator.Validate(context.InstanceToValidate);
            if (preValidationResult.IsValid)
            {
                return true;
            }
    
            foreach(var error in preValidationResult.Errors)
            {
                result.Errors.Add(new ValidationFailure(error.PropertyName, error.ErrorMessage, error.AttemptedValue));
            }
    
            return false;
        }
    }
    

    为所有基本模型创建验证器后,您可以从它继承以进行 ChildModel 验证:

    public class ChildModelValidator : BaseModelValidator<ChildModel>
    {
        public ChildModelValidator() 
            : base()
        {
            RuleFor(x => x.IdOfSthInDb)
                .MustAsync(ItemMustExists)
                .WithMessage("Item does not exist.");
        }
    
        private Task<bool> ItemMustExists(int arg1, CancellationToken arg2)
        {
            return Task.FromResult(false); // some logic here
        }
    }
    

    就是这样!

    【讨论】:

      【解决方案2】:

      我认为十六进制代码可以解决您的问题:

      var basicValidator = new BasicValidation();
      RuleFor(m => m).SetValidator(basicValidator));
      
      When(m => basicValidator.Validate(m).IsValid, () => 
      {
          RuleFor(m => m.IdOfSthInDb)
              .MustAsync(ItemMustExists)
              .WithMessage("Item does not exist.");
      });
      

      【讨论】:

      • 几乎是我想要的 :-) 它给了我一些想法,但我必须得到“类似的任务”才能完成它。 - 但是仍然需要每个模型的“BasicValidation”类。
      猜你喜欢
      • 1970-01-01
      • 2021-12-02
      • 2021-07-13
      • 1970-01-01
      • 2012-10-03
      • 2017-12-14
      • 2012-10-23
      • 1970-01-01
      • 2018-09-01
      相关资源
      最近更新 更多