2012-03-08 65 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; 
    } 
}