使用表达式定义验证规则

时间:2015-07-13 11:44:39

标签: c# lambda expression

我想创建一个通用的验证类,所以我可以这样做:

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

我不确定如何编写方法定义并进行评估?

AddRequiredstring AddRangeint取数字类型double,主要是decimalMainActivity,等)

3 个答案:

答案 0 :(得分:1)

应该有一些库可用于此任务。但是,你可以自己写一些关于lambdas的经验。我已经为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;
        }
    }

答案 1 :(得分: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可以包装值类型。但是,传递和存储Func<T,...>对象的方式应该可以让您了解如何实现其余部分。

答案 2 :(得分: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);