FluentValidation 子验证器中的 PropertyName
PropertyName in FluentValidation child validators
我正在 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" 在前面。我一直无法弄清楚如何进行这项工作。有简单的方法吗?我做错了整件事吗?
事实证明这很简单,只需要传入 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);
}
我正在 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" 在前面。我一直无法弄清楚如何进行这项工作。有简单的方法吗?我做错了整件事吗?
事实证明这很简单,只需要传入 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);
}