Make Validation generic on the type of x, define methods taking Func<x,object> or some other type as needed, store these functions, and call them from the Validate(x) method:
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;
}
}
This implementation is very skeletal - it needs null checks in many places to be useful. In addition, it's not very efficient, because IComparable and object could wrap value types. However, the way of passing and storing Func<T,...> objects should give you an idea of how to implement the rest of it.
AddRequiredandAddRangedo?