0

使用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");

这种方法有两个问题:

  1. 我不喜欢使用字符串作为进程名称。我想使用更强类型的方法。例如能够使用标记接口或属性。
  2. 在我的单元测试中,我无法设置 IValidator 的 Validate 方法,因为您不能在 Moq 中使用可选参数。


Mock<IValidator<A>> _mockValidator = new Mock<IValidator<A>>();
_mockValidator.Setup(x => x.Validate(new A(), ruleSet: "ProcessA"));
第二行生成运行时错误:表达式树可能不包含命名参数规范。如果你想将没有命名参数的 ruleSet 参数传递给 Validate 方法,你必须提供一个“IValidatorSelector 选择器”对象。但是这个接口没有记录。

4

2 回答 2

1

是什么阻止你创建一个帮助类,你可以在其中使用变量、数据结构,以及任何你喜欢的东西来防止硬编码字符串参数的使用?另外,不要忘记使用枚举的可能性。

是什么阻止您创建一个实现 IValidator 的类,您还可以在其中实现您需要的自定义功能?

于 2012-06-12T09:51:54.017 回答
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);
于 2018-03-02T05:30:44.653 回答