代码之家  ›  专栏  ›  技术社区  ›  nilphilus

FluentValidation-预验证/无代码重复的条件验证

  •  7
  • nilphilus  · 技术社区  · 7 年前

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

    现在,我确实在“主验证器”中创建了一个私有的“BasicValidation”类,并执行以下操作:

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

    2 回复  |  直到 7 年前
        1
  •  3
  •   Electrionics    7 年前

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

    为所有基本模型创建验证程序后,您可以从中继承以进行子模型验证:

    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
  •  2
  •   Electrionics    7 年前

    我认为hext代码可以解决您的问题:

    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.");
    });