2015-07-13 33 views
0

我想創建一個通用的驗證類,所以我可以這樣做:使用表達式定義的驗證規則

Validation v = new Validation(); 
v.AddRequired(x => this.Name); 
v.AddRange(x => x.this.Age, 5, 65); 

我不確定要怎麼寫的方法定義和做出評價?

AddRequired將採取stringAddRange會採取一個數字類型(int,主要也是doubledecimal等)

+0

我應該'AddRequired'和'AddRange'嗎? –

+1

如果你不是瘋狂地設置自己實現它,我會推薦FluentValidation:https://github.com/JeremySkinner/FluentValidation。這是一個用於驗證的非常靈活的庫 –

+0

另請參閱Code Contracts:https://msdn.microsoft.com/en-us/library/dd264808%28v=vs.110%29.aspx – sblandin

回答

0

的做法是:

class ObjectToBeValidated { 
    public string Name { get; set; } 
    public int Age { get; set; } 
} 

class Validation { 
    private List<Expression<Func<ObjectToBeValidated, bool>>> requiredExpressions; 
    private List<Expression<Func<ObjectToBeValidated, bool>>> rangeExpressions; 

    public void AddRequired(Expression<Func<ObjectToBeValidated, string>> expression) 
    { 
     Expression<Func<ObjectToBeValidated, bool>> checkRequired = (p => !string.IsNullOrEmpty(expression.Compile().Invoke(p))); 
     requiredExpressions.Add(checkRequired); 
    } 

    public void AddRange(Expression<Func<ObjectToBeValidated, int>> expression, int min, int max) 
    { 
     Func<ObjectToBeValidated, int> compiledFunc = expression.Compile(); 
     Expression<Func<ObjectToBeValidated, bool>> checkRange = (p => compiledFunc.Invoke(p) >= min && compiledFunc.Invoke(p) < max); 
     rangeExpressions.Add(checkRange); 
    } 
} 

這只是存儲您的條件List<T>的。 然後,您將有一個方法添加到您的Validation類計算表達式:

public bool IsValid(ObjectToBeValidated testObject) 
    { 
     return requiredExpressions.All(p => p.Compile().Invoke(testObject)) 
      && rangeExpressions.All(p => p.Compile().Invoke(testObject)); 
    } 

然後,使用這樣的:

validator.AddRequired(p => p.Name); 
validator.AddRange(p => p.Age, 6, 15); 

var myObject = new ObjectToBeValidated(); 
var result = validator.IsValid(myObject); 
+0

當然,您也可以在AddRequired和AddRange方法中編譯表達式,將它們添加到List >中,然後在「IsValid」函數中調用它們。另外,對於每個條件類型,您可以對所有條件使用一個列表,而不是像我的示例那樣。 – LInsoDeTeh

1

應該有一些可用於此任務庫。然而,你可以通過自己寫這個來獲得lambda的一些經驗。我已經爲AddRange做了一個草案實施,我希望你能從這裏走得更遠。

public class Validation<T> { 
     private List<RangeValidation> _rangeValidations = new List<RangeValidation>(); 

     public void AddRange(Func<T, int> func, int min, int max) { 
      _rangeValidations.Add(new RangeValidation() { 
       func = func, 
       min = min, 
       max = max 
      }); 
     } 

     public bool Validate(T obj) { 
      foreach (var rangeValidation in _rangeValidations) { 
       int value = rangeValidation.func(obj); 
       if (value < rangeValidation.min || value > rangeValidation.max) 
        return false; 
      } 
      return true; 
     } 

     private class RangeValidation { 
      public Func<T, int> func; 
      public int min, max; 
     } 
    } 
0

Validation通用對x類型,定義採取Func<x,object>或一些其他類型的需要的方法,存儲這些功能,並從Validate(x)方法叫他們:

class Validation<T> { 
    private IList<Tuple<Func<T,IComparable>,IComparable,IComparable>> rangeChecks = new List<Tuple<Func<T,IComparable>,IComparable,IComparable>>(); 
    private IList<Func<T,object>> nullChecks = new List<Func<T,object>>; 
    public AddRequired(Func<T,object> f) { 
     nullChecks.Add(f); 
    } 
    public AddRange(Func<T,IComparable> f, IComparable low, IComparable high) { 
     rangeChecks.Add(Tuple.Create(f, low, high)); 
    } 
    public bool Validate(T x) { 
     foreach(var t in rangeChecks) { 
      var f = t.Item1; 
      var low = t.Item2; 
      var high = t.Item3; 
      var val = f(x); 
      if (v.CompareTo(low) < 0 || v.CompareTo(high) > 0) { 
       return false; 
      } 
     } 
     foreach (var t in nullChecks) { 
      if (t(x) == null) { 
       return false; 
      } 
     } 
     return true; 
    } 
} 

這個實現是非常骨骼 - 它需要在許多地方空檢查是有用的。另外,效率不高,因爲IComparableobject可以包裝值類型。但是,傳遞和存儲對象的方式應該讓您瞭解如何實現其餘部分。