Ok, here\'s a tricky one. Hopefully there is an expression guru here who can spot what I am doing wrong here, cause I am just not getting it.
I am building up expression
I refactored your methods a bit to make the compiler a bit happier:
public static Expression> AndWithin(
this Expression> original,
IEnumerable> range, Expression> field) where TField : IComparable
{
return original.And(range.GetPredicateFor(field));
}
static Expression> GetPredicateFor
(this IEnumerable> range, Expression> selector) where TValue : IComparable
{
var param = Expression.Parameter(typeof(TSource), "x");
if (range == null || !range.Any())
return Expression.Lambda>(Expression.Constant(false), param);
Expression body = null;
foreach (var r in range)
{
Expression> BT = (val, min, max) => val.CompareTo(min) >= 0 && val.CompareTo(max) <= 0;
var newPart = Expression.Invoke(BT, param,
Expression.Constant(r.Start, typeof(TValue)),
Expression.Constant(r.End, typeof(TValue)));
body = body == null ? newPart : (Expression)Expression.OrElse(body, newPart);
}
return Expression.Lambda>(body, param);
}
Both have the added restriction of IComparable
(the only change to the first method).
In the second, I'm doing the comparison via a Func
Expression implementation, notice that the func is created inside the loop...it's the second addition of this (what it thinks is the same...) expression in the old method that's blowing up.
Disclaimer: I still don't fully understand why your previous method didn't work, but this alternative approach bypasses the problem. Let me know if this isn't what you're after and we'll try something else.
Also, kudos on ASKING a question well, a sample project is exemplary.