我们说我有以下课程:
class MyClass
{
public string Foo { get; set; }
public string Bar { get; set; }
public string Baz { get; set; }
}
和验证规则如下:
RuleFor(c => c.Foo).NotEmpty();
RuleFor(c => c.Bar).NotNull(); // Bar is allowed to be empty string
RuleFor(c => c.Baz).NotEmpty();
有没有办法表达一个默认规则,用于验证没有指定特定规则的任何属性?这样的东西应该给出与上面相同的验证结果吗?
RuleFor(c => c.Bar).NotNull();
DefaultRule().NotEmpty();
答案 0 :(得分:1)
所以,我向Jeremy Skinner(FluentValidation的创建者)提出了同样的问题,并很快得到了以下答案。
不,我不敢开箱即可。 FluentValidation背后的想法是提供一种方法来明确定义针对特定属性的强类型规则。这种方式违背了这个目的,所以我不喜欢包括这样的东西。 话虽这么说,如果你真的想要这个功能,你可以将它构建为扩展。您必须执行以下操作:
这是一个简单的例子(未经测试)。您需要引入缓存以防止对验证器的每个实例化进行反映:
public static class DefaultRuleExtension
{
public static void DefaultRule<T>(this AbstractValidator<T> validator, Action<IRuleBuilder<T, object>> defaultRuleBuilder)
{
var existingPropertiesWithRules = validator.OfType<PropertyRule>().Select(x => x.PropertyName).ToList();
var properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(x => !existingPropertiesWithRules.Contains(x.Name));
//TODO: Make sure you cache the properties and the expression tree so the reflection isn't performed on every instantiation.
foreach (var property in properties)
{
var expression = BuildGetterExpression<T>(property);
var rule = PropertyRule.Create(expression);
validator.AddRule(rule);
var ruleBuilder = new RuleBuilder<T, object>(rule, validator);
defaultRuleBuilder(ruleBuilder);
}
}
private static Expression<Func<T, object>> BuildGetterExpression<T>(PropertyInfo prop)
{
var param = Expression.Parameter(typeof(T), "x");
Expression expression = Expression.PropertyOrField(param, prop.Name);
if (prop.PropertyType.IsValueType)
expression = Expression.Convert(expression, typeof(object));
return Expression.Lambda<Func<T, object>>(expression, param);
}
}
可以这样:
public class DemoValidator : AbstractValidator<Person> {
public DemoValidator() {
this.DefaultRule(r => {
r.NotEmpty();
});
}
}