FluentValidation子验证器中的PropertyName

时间:2019-04-28 06:47:11

标签: c# fluentvalidation

我正在FluentValidation中尝试一些奇怪的事情,但我似乎还无法使其正常工作。我正在验证的模型中包含字符串,并且我想对它们解析到的对象进行验证,例如,序列化为字符串的日期现在早于该日期,例如:

RuleFor(x => x.SentDateString).AsDate(d => d.DateInPast());

我认识到这样做的正常方法是使模型本身包含已分析的日期和其他对象,然后验证反序列化的数据,但是我有这样做的理由。

我的工作方式如下:

// general mechanism for adding "casting" rules
public static IRuleBuilderOptions<T, TFrom> Xform<T, TFrom, TTo>(
    this IRuleBuilder<T, TFrom> ruleBuilder,
     Func<TFrom, TTo> xform,
     Func<IRuleBuilder<TFrom, TTo>, IRuleBuilderOptions<TFrom, TTo>> innerRules)
{
    var innerValidator = new InlineValidator<TFrom>() {
        v => innerRules(v.RuleFor(x => xform(x)))
    };
    return ruleBuilder.SetValidator(innerValidator);
}

// specific rule for making a date
public static IRuleBuilder<T, string> AsDate<T>(
    this IRuleBuilder<T, string> ruleBuilder,
    Func<IRuleBuilder<string, DateTime>, IRuleBuilderOptions<string, DateTime>> innerRules)
{
    Func<string, DateTime> parseDate = (s) =>
    {
        DateTime d;
        DateTime.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out d);
        return d;
    };
    return Xform(ruleBuilder, parseDate, innerRules);
}

// inner rule used in validating the date object
public static IRuleBuilderOptions<T, DateTime> DateInPast<T>(this IRuleBuilder<T, DateTime> ruleBuilder) =>
    ruleBuilder.LessThan(DateTime.Now.Add(TimeSpan.FromMinutes(5)))
        .WithMessage("{PropertyName} must be in the past");

这确实验证了属性!但是,属性名称不会传递给子验证程序,因此我收到如下消息:

  must be in the past

在此之前我希望看到“ SentDateString”。我一直无法弄清楚如何进行这项工作。有没有简单的方法?我整个事情做错了吗?

1 个答案:

答案 0 :(得分:0)

事实证明这很简单,只需要传递IRuleBuilderOptions而不是IRuleBuilder,然后使用Configure复制显示名称即可。

public static IRuleBuilderOptions<T, TFrom> Xform<T, TFrom, TTo>(
    this IRuleBuilderOptions<T, TFrom> ruleBuilder,
    Func<TFrom, TTo> xform,
    Func<IRuleBuilder<TFrom, TTo>, IRuleBuilderOptions<TFrom, TTo>> innerRules)
{
    var innerValidator = new InlineValidator<TFrom>() {
        v => innerRules(v.RuleFor(x => xform(x)))
                .Configure(c1 => ruleBuilder.Configure(c2 => c1.DisplayName = c2.DisplayName))
    };
    return ruleBuilder.SetValidator(innerValidator);
}