Правило применения FluentValidation, только если значение не пустое - PullRequest
0 голосов
/ 16 мая 2019

У меня есть следующий метод расширения для FluentValidation:

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

Я хочу применить это правило, только если свойство имеет что-то на нем, если это строка null или emptyПравило не должно проверяться.

В классе проверки вызова я могу сделать это следующим образом:

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

Это работает, но затем я должен поставить этот вызов When на каждый вызовметод.Есть ли способ переместить вызов When в метод расширения?

Ответы [ 2 ]

1 голос
/ 16 мая 2019
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");
                }
            });
        }
1 голос
/ 16 мая 2019

Добавление расширения When Builder ниже дает вам доступ к значению свойства.Вы можете повторно использовать это и для других проверок.

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);
        });
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...