At first I had my suspicions, but now I can confirm this.
You combine two lambdas that have two completely different instances of their parameters. Parameter instances cannot be replaced, even if they have the same name and type. They are effective parameters in different areas. When you tried to call one of the expressions with the wrong parameter object, in this case there is chaos, stack overflow.
What you need to do is instantiate a new parameter (or reuse it) and retrain your lambda bodies to use this new parameter. I suspect that will fix it. And to take a step further, you must correctly combine these expressions, restoring them, instead of binding them together as method calls. I doubt that query providers will like these calls in any way.
Try this implementation of your And() and Or() methods along with this helper method for recovery:
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) { // reuse the first expression parameter var param = expression1.Parameters.Single(); var left = expression1.Body; var right = RebindParameter(expression2.Body, expression2.Parameters.Single(), param); var body = Expression.AndAlso(left, right); return Expression.Lambda<Func<T, bool>>(body, param); } public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) { var param = expression1.Parameters.Single(); var left = expression1.Body; var right = RebindParameter(expression2.Body, expression2.Parameters.Single(), param); var body = Expression.OrElse(left, right); return Expression.Lambda<Func<T, bool>>(body, param); } private static Expression RebindParameter(Expression expr, ParameterExpression oldParam, ParameterExpression newParam) { switch (expr.NodeType) { case ExpressionType.Parameter: var asParameterExpression = expr as ParameterExpression; return (asParameterExpression.Name == oldParam.Name) ? newParam : asParameterExpression; case ExpressionType.MemberAccess: var asMemberExpression = expr as MemberExpression; return asMemberExpression.Update( RebindParameter(asMemberExpression.Expression, oldParam, newParam)); case ExpressionType.AndAlso: case ExpressionType.OrElse: case ExpressionType.Equal: case ExpressionType.NotEqual: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: var asBinaryExpression = expr as BinaryExpression; return asBinaryExpression.Update( RebindParameter(asBinaryExpression.Left, oldParam, newParam), asBinaryExpression.Conversion, RebindParameter(asBinaryExpression.Right, oldParam, newParam)); case ExpressionType.Call: var asMethodCallExpression = expr as MethodCallExpression; return asMethodCallExpression.Update( RebindParameter(asMethodCallExpression.Object, oldParam, newParam), asMethodCallExpression.Arguments.Select(arg => RebindParameter(arg, oldParam, newParam))); case ExpressionType.Invoke: var asInvocationExpression = expr as InvocationExpression; return asInvocationExpression.Update( RebindParameter(asInvocationExpression.Expression, oldParam, newParam), asInvocationExpression.Arguments.Select(arg => RebindParameter(arg, oldParam, newParam))); case ExpressionType.Lambda: var asLambdaExpression = expr as LambdaExpression; return Expression.Lambda( RebindParameter(asLambdaExpression.Body, oldParam, newParam), asLambdaExpression.Parameters.Select(param => (ParameterExpression)RebindParameter(param, oldParam, newParam))); default: // you should add cases for any expression types that have subexpressions return expr; } }
What the rewriting method does is search (by name) and return an expression in which all ParameterExpression in the expression tree are replaced with an instance of another ParameterExpression . This does not modify existing expressions, but if necessary restores the expression that creates new updated expressions. In other words, it returns a new expression that should be used as a replacement for the one you are redoing.
The idea is to study Expression and determine what type it is. If it is a ParameterExpression , check to see if it has the same name as the parameter we are looking for. If so, return our new parameter, otherwise return it, since we should not change it. If the expression is not a parameter, it is likely to be an expression that contains subexpressions and needs to be replaced.
A BinaryExpression will have a Left operand and a Right operand, both expressions. Both of them should be a rebound, since somewhere down their expression trees may be a parameter that needs to be replaced. The Update() method will replace the current expression with the same with the new subexpressions. In this case, we wanted to (possibly) update the Left and Right subexpressions.
MethodCallExpression and InvocationExpression have the same idea, but the tree is a little different. It has an Object expression (or Expression in case of a call) that represents the instance (or delegate / lambda) that you want to call. ( MethodCallExpression also has MethodInfo , which represents the instance method to call). They also have Arguments (all expressions) that are used as arguments to invoke. These expressions should potentially be restored.
You can think of the RebindParameter() method as the "super" - Update() method, which updates the parameters in the entire expression tree.
To further illustrate the illustration, to help visualize how the tree looks and what changes. Note that since there are replacements here, most subtrees will be new instances.
[ 
Now there was something that I did not understand, was ExpressionVisitor . I wish I had noticed this before. This will improve the work of the picker. Instead of publishing the full code here, here it is on pastebin . Then, to use it:
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) {