仅当值不为空时,FluentValidation应用规则

时间:2019-05-16 05:16:00

标签: c# fluentvalidation

对于FluentValidation,我具有以下扩展方法:

    public static IRuleBuilderOptions<T, string> MustHasLengthBetween<T>(this IRuleBuilder<T, string> rule, int min, int max)
    {
        return rule
            .Length(min, max).WithMessage(someCustomMessage);
    }

我只想在属性上有内容时才应用此规则,如果它是nullempty字符串,则不应验证此规则。

在调用验证类中,我可以这样:

        RuleFor(a => a.SomeProperty)
            .MustHasLengthBetween(5, 10)
            .When(x => !String.IsNullOrEmpty(x.SomeProperty))

它可以工作,但是然后我必须将此When调用放在每个调用方法上。有什么方法可以将When调用移至扩展方法?

2 个答案:

答案 0 :(得分:1)

在下面添加扩展名When构建器可让您访问属性值。您也可以将其与其他验证一起使用。

public static IRuleBuilderOptions<T, TProperty> When<T, TProperty>(this IRuleBuilderOptions<T, TProperty> rule, Func<T, TProperty, bool> predicate, ApplyConditionTo applyConditionTo = ApplyConditionTo.AllValidators)
{
    return rule.Configure(config => {
        config.ApplyCondition(ctx => predicate((T)ctx.Instance, (TProperty)ctx.PropertyValue), applyConditionTo);
    });
}

测试

public class UnitTest1
{
    [Fact]
    public void Should_validate_length ()
    {
        var ok1 = new Model { MyProperty = null };
        var ok2 = new Model { MyProperty = "" };
        var ok3 = new Model { MyProperty = "55555" };
        var fail = new Model { MyProperty = "1" };

        var v = new ModelValidator ();

        v.ValidateAndThrow (ok1);
        v.ValidateAndThrow (ok2);
        v.ValidateAndThrow (ok3);

        Should.Throw<ValidationException> (() => v.ValidateAndThrow (fail));
    }

    public class Model
    {
        public string MyProperty { get; set; }
    }

    public class ModelValidator : AbstractValidator<Model>
    {
        public ModelValidator ()
        {
            RuleFor (x => x.MyProperty)
                .MustHaveLengthBetween (5, 10);
        }
    }
}

public static class Extensions
{
    public static IRuleBuilderOptions<T, string> MustHaveLengthBetween<T> (this IRuleBuilder<T, string> rule, int min, int max)
    {
        return rule
            .Length (min, max).WithMessage ("AGAGA")
            .When ((model, prop) => !string.IsNullOrEmpty (prop));
    }

    /// <summary>
    /// Predicate builder which makes the validated property available
    /// </summary>
    /// <param name="IRuleBuilderOptions<T"></param>
    /// <param name="rule"></param>
    /// <param name="predicate"></param>
    /// <param name="applyConditionTo"></param>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="TProperty"></typeparam>
    /// <returns></returns>
    public static IRuleBuilderOptions<T, TProperty> When<T, TProperty> (this IRuleBuilderOptions<T, TProperty> rule, Func<T, TProperty, bool> predicate, ApplyConditionTo applyConditionTo = ApplyConditionTo.AllValidators)
    {
        return rule.Configure (config =>
        {
            config.ApplyCondition (ctx => predicate ((T) ctx.Instance, (TProperty) ctx.PropertyValue), applyConditionTo);
        });
    }
}

答案 1 :(得分:1)

public static IRuleBuilderInitial<T, string> MustHasLengthBetween<T>(this IRuleBuilder<T, string> rule, int min, int max)
        {
            return rule.Custom((obj, context) =>
            {
                if (!String.IsNullOrEmpty(obj) && (obj.Length < min || obj.Length > max))
                {
                    context.AddFailure("custom message");
                }
            });
        }