使用http://fluentvalidation.codeplex.com/
将验证规则绑定到特定流程的最佳做法是什么?目前我正在使用“规则集”功能将规则分组到不同的进程:
public class ObjAValidation: AbstractValidator<A>
{
public ObjAValidation()
{
RuleSet("ProcessA", () =>
{
RuleFor(x => ...);
RuleFor(x => ...);
});
RuleSet("ProcessB", () =>
{
RuleFor(x => ...);
RuleFor(x => ...);
});
}
}
然后使用以下方式验证:
var a = new A(){...};
IValidator<A> validator = new ObjAValidation();
var result = validator.Validate(a, ruleSet: "ProcessA");
这种方法有两个问题:
Mock<IValidator<A>> _mockValidator = new Mock<IValidator<A>>();
_mockValidator.Setup(x => x.Validate(new A(), ruleSet: "ProcessA"));
第二行生成运行时错误:表达式树可能不包含命名参数规范。如果要将没有命名参数的ruleSet参数传递给Validate方法,则必须提供“IValidatorSelector选择器” “对象。但是没有记录这个界面。
答案 0 :(得分:0)
是什么阻止您创建一个帮助器类,您可以使用变量,数据结构,任何您喜欢的东西来阻止使用硬编码字符串参数?另外,不要忘记使用枚举的可能性。
是什么阻止您创建一个实现IValidator的类,您还可以在其中实现您需要的自定义功能?
答案 1 :(得分:0)
我遇到了同样的问题,并找出了你不能通过Moq等模拟这个方法的原因validator.Validate(a, ruleSet: "ProcessA");
是因为它是一个扩展方法,Moq不能模拟静态方法。
有人在FluentValidation问题中提出了同样的问题:https://github.com/JeremySkinner/FluentValidation/issues/191
简单的解决方案是不使用扩展方法而是使用即时方法IValidator.validate(context)
。您需要做的就是构建上下文。从这里查看源代码:https://github.com/JeremySkinner/FluentValidation/blob/master/src/FluentValidation/DefaultValidatorExtensions.cs#L819
if(ruleSet != null) {
var ruleSetNames = ruleSet.Split(',', ';').Select(x => x.Trim());
selector = ValidatorOptions.ValidatorSelectors.RulesetValidatorSelectorFactory(ruleSetNames.ToArray());
}
var context = new ValidationContext<T>(instance, new PropertyChain(), selector);
return validator.Validate(context);