我正在使用FluentValidation
我想使用以下方法进行范围验证:
InclusiveBetween
RuleFor(x => x.Height)
.InclusiveBetween(x=> x.min, x.max).
我希望能够从'和'到'从模型中动态赋值而不是在验证器中进行硬编码
这可能吗?
由于
答案 0 :(得分:2)
嗯,FluentValidation中没有任何内容。
但是你可以编写自己的扩展方法(和验证器),类似的东西(快速拍摄,所以你必须做得更好,但你已经有了这个想法)。
//the extension method
public static class ValidationExtensions
{
public static IRuleBuilder<T, TProperty> InclusiveBetween<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, Expression<Func<T, TProperty>> fromExpression, Expression<Func<T, TProperty>> toExpression)
{
var fromFunc = leftExpression.Compile();
var toFunc = rightExpression.Compile();
return ruleBuilder.SetValidator(new InclusiveBetweenPropertyValidator(fromFunc.CoerceToNonGeneric(), fromExpression.GetMember(), toFunc.CoerceToNonGeneric(), toExpression.GetMember()));
}
}
然后是Validator类
public class InclusiveBetweenPropertyValidator : PropertyValidator, IBetweenValidator, IPropertyValidator
{
public Func<object, object> FromFunc { get; set; }
public MemberInfo FromMemberInfo { get; set; }
public Func<object, object> ToFunc { get; set; }
public MemberInfo ToMemberInfo { get; set; }
public IComparable From { get; private set; }
public IComparable To { get; private set; }
public InclusiveBetweenPropertyValidator(Func<object, object> fromFunc, MemberInfo fromMember, Func<object, object> toFunc, MemberInfo toMember)
: base((() => Messages.inclusivebetween_error))
{
FromFunc = fromFunc;
FromMemberInfo = fromMember;
ToFunc = toFunc;
ToMemberInfo = toMember;
}
protected override bool IsValid(PropertyValidatorContext context)
{
var comparable = (IComparable)context.PropertyValue;
From = (IComparable)this.FromFunc(context.Instance);
To = (IComparable)this.ToFunc(context.Instance);
if (comparable == null || FluentValidation.Internal.Comparer.GetComparisonResult(comparable, From) >= 0 && FluentValidation.Internal.Comparer.GetComparisonResult(comparable, To) <= 0)
return true;
context.MessageFormatter.AppendArgument("From", string.Format("{0} ({1})", FromMemberInfo.Name, From)).AppendArgument("To", string.Format("{0} ({1})",ToMemberInfo.Name, To)).AppendArgument("Value", context.PropertyValue);
return false;
}
}
用法:
RuleFor(x => x.Height)
.InclusiveBetween(x=> x.min, x.max)
答案 1 :(得分:0)
这类似于Raphaël的回答,但更多地是按情况使用,而不是一般用法扩展。
RuleFor(x => x).Must(HeightValidation);
private static bool HeightValidation(Model m)
{
return m.Height >= m.min && m.Height <= m.max;
}
答案 2 :(得分:0)
如果您不想编写扩展名,则可以使用Predicate Validator的附加重载-它也接受父对象的实例,如下所示:
RuleFor(x => x.Height)
.Must((model, height) => height >= model.Min && height <= model.Max);
答案 3 :(得分:0)
让我们假设您的模型如下:
public class YourModel
{
public int Height { get; set; }
public int Min { get; set; }
public int Max { get; set; }
}
然后验证如下:
public class YourModelValidation : AbstractValidator<YourModel>
{
public YourModelValidation(int min,int max)
{
RuleFor(x => x.Height).InclusiveBetween(min, max);
}
}
则验证用法为:
var validation = new YourModelValidation(model.Min,model.Max).Validate(model);
如您所见,动态参数在验证的构造函数中传递。
您可以将模型或dto传递为构造函数参数