我想創建一個通用的驗證類,所以我可以這樣做:使用表達式定義的驗證規則
Validation v = new Validation();
v.AddRequired(x => this.Name);
v.AddRange(x => x.this.Age, 5, 65);
我不確定要怎麼寫的方法定義和做出評價?
凡AddRequired
將採取string
和AddRange
會採取一個數字類型(int
,主要也是double
,decimal
等)
我想創建一個通用的驗證類,所以我可以這樣做:使用表達式定義的驗證規則
Validation v = new Validation();
v.AddRequired(x => this.Name);
v.AddRange(x => x.this.Age, 5, 65);
我不確定要怎麼寫的方法定義和做出評價?
凡AddRequired
將採取string
和AddRange
會採取一個數字類型(int
,主要也是double
,decimal
等)
的做法是:
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);
當然,您也可以在AddRequired和AddRange方法中編譯表達式,將它們添加到List
應該有一些可用於此任務庫。然而,你可以通過自己寫這個來獲得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;
}
}
讓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;
}
}
這個實現是非常骨骼 - 它需要在許多地方空檢查是有用的。另外,效率不高,因爲IComparable
和object
可以包裝值類型。但是,傳遞和存儲對象的方式應該讓您瞭解如何實現其餘部分。
我應該'AddRequired'和'AddRange'嗎? –
如果你不是瘋狂地設置自己實現它,我會推薦FluentValidation:https://github.com/JeremySkinner/FluentValidation。這是一個用於驗證的非常靈活的庫 –
另請參閱Code Contracts:https://msdn.microsoft.com/en-us/library/dd264808%28v=vs.110%29.aspx – sblandin