简体   繁体   English

FluentValidation 子验证器中的 PropertyName

[英]PropertyName in FluentValidation child validators

I'm trying something a little odd in FluentValidation and I can't quite seem to make it work.我在 FluentValidation 中尝试了一些奇怪的东西,但我似乎无法让它发挥作用。 The model I'm validating has strings in it and I would like run validations on the objects they parse to, for example, that a date serialized as a string is before right now, like so:我正在验证的模型中有字符串,我想对它们解析的对象运行验证,例如,序列化为字符串的日期在现在之前,如下所示:

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

I recognize that the normal way to do that is make the model itself contain the parsed dates and other objects and then validate the deserialized data, but I have my reasons for wanting to do it this way.我认识到通常的做法是让模型本身包含解析的日期和其他对象,然后验证反序列化的数据,但我有理由想要这样做。

I have this working like this:我有这样的工作:

// 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");

This does validate the property!这确实验证了属性! However, the property name doesn't transfer through to the child validator, so I get messages like:但是,属性名称不会传递给子验证器,因此我收到如下消息:

  must be in the past

Where I expected "SentDateString" at the front of that.我期望在前面的“SentDateString”。 I haven't been able to figure out how to make that work.我一直无法弄清楚如何使它起作用。 Is there an easy way?有没有简单的方法? Am I doing the whole thing wrong?我做错了整件事吗?

This turned out to be pretty easy, just needed to pass in an IRuleBuilderOptions instead of an IRuleBuilder and then use Configure to copy over the display name.结果证明这非常简单,只需要传入一个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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM