流畅验证 - 将验证与特定流程最佳实践联系起来

问题描述 投票:0回答:2

使用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"));
Second line generates a run time error: An expression tree may not contain a named argument specification. And if you want to pass the ruleSet argument without a named argument to Validate method you have to provide a "IValidatorSelector selector" object. But this interface is not documented.
c# validation c#-4.0 moq fluentvalidation
2个回答
0
投票

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

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


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);
© www.soinside.com 2019 - 2024. All rights reserved.