2012-03-08 74 views
2

给出一个验证器类,看起来像这样流利的验证规则,子集和嵌套

public class SomeValidator : AbstractValidator<SomeObject> 
{ 
     public SomeValidator(){ 
      RuleSet("First", 
       () => { 
        RuleFor(so => so.SomeMember).SetValidator(new SomeMemberValidator()) 
      }); 
      RuleSet("Second", 
       () => ... Code Does Not Matter ...); 
      RuleSet("Third", 
       () => ... Code Does Not Matter ...); 
     } 
} 

,另一个做内部构件验证

public class SomeMemberValidator: AbstractValidator<SomeMember> 
{ 
     public SomeValidator(){ 
      RuleSet("Fourth", 
       () => { 
        ... Code Does Not Matter ... 
      }); 
     } 
} 

的问题是,我想运行特定的规则集: “第一”,“第二”和“第四”。我不想要“第三”运行。

鉴于Validate方法签名只需要一个规则集参数,我没有看到任何方式来做到这一点。有“*”,但我不想运行所有规则。

请帮忙。

回答

5

您可以执行多个RuleSet,但我不认为您可以执行内部RuleSet。

validator.Validate(new ValidationContext<SomeObject>(person, new PropertyChain(), new RulesetValidatorSelector("First", "Second", "Fourth"))); 

Source

另一种选择是调查的源代码,并试图想这样做的一种方式。 ValidationContext的第三个参数是一个接口,IValidatorSelector,也许你可以有一个自定义类的运气。

+0

我希望避免冒险进入源代码,如果可能的话,但我们会看到。谢谢您的帮助。 – Alwyn 2012-03-09 22:27:44

6

您可以使用验证器构造函数而不是RuleSet作为此问题的解决方法。 只需在验证器类中创建枚举,然后在创建验证器时使用它的值。

我这样正确的规则将被激活,取决于在构造函数中设置了什么模式。

public class UserValidator : AbstractValidator<User> 
{ 
    public enum Mode 
    { 
     Create, 
     Edit 
    } 

    public UserValidator() 
    { 
     // Default rules... 
    } 

    public UserValidator(UserValidator.Mode mode) 
     : this() 
    { 
     if (mode == Mode.Edit) 
     { 
      // Rules for Edit... 

      RuleFor(so => so.SomeMember) 
       .SetValidator(
        new SomeMemberValidator(SomeMemberValidator.Mode.SomeMode)) 
     } 

     if (mode == Mode.Create) 
     { 
      // Rules for Create... 

      RuleFor(so => so.SomeMember) 
       .SetValidator(
        new SomeMemberValidator()) 
     } 
    } 
} 

我认为它实际上比使用RuleSet更灵活的方法。

只有一个关于FluentValidation MVC整合小问题: User类不能有属性[Validator(typeof(UserValidator))]因为UserValidator会然后使用默认的构造函数,然后才能做控制器的方法创建任何东西。

必须手动创建和调用验证器。像这样的例子:

public class UserController : Controller 
{ 
    [HttpPost] 
    public ActionResult Create(User userData) 
    { 
     var validator = new UserValidator(UserValidator.Mode.Create); 

     if (ValidateWrapper(validator, userData, this.ModelState)) 
     { 
      // Put userData in database... 
     } 
     else 
     { 
      // ValidateWrapper added errors from UserValidator to ModelState. 
      return View(); 
     } 
    } 

    private static bool ValidateWrapper<T>(FluentValidation.AbstractValidator<T> validator, T data, ModelStateDictionary modelState) 
    { 
     var validationResult = validator.Validate(data); 

     if (!validationResult.IsValid) 
     { 
      foreach (var error in validationResult.Errors) 
       modelState.AddModelError(error.PropertyName, error.ErrorMessage); 

      return false; 
     } 

     return true; 
    } 
}