I have two expressions of type Expression
and I want to take to OR, AND or NOT of these and get a new expression of the same type
You can use Expression.AndAlso / OrElse to combine logical expressions, but you have to make sure the ParameterExpressions are the same.
I was having trouble with EF and the PredicateBuilder so I made my own without resorting to Invoke, that I could use like this:
var filterC = filterA.And(filterb);
Source code for my PredicateBuilder:
public static class PredicateBuilder {
public static Expression> And(this Expression> a, Expression> b) {
ParameterExpression p = a.Parameters[0];
SubstExpressionVisitor visitor = new SubstExpressionVisitor();
visitor.subst[b.Parameters[0]] = p;
Expression body = Expression.AndAlso(a.Body, visitor.Visit(b.Body));
return Expression.Lambda>(body, p);
}
public static Expression> Or(this Expression> a, Expression> b) {
ParameterExpression p = a.Parameters[0];
SubstExpressionVisitor visitor = new SubstExpressionVisitor();
visitor.subst[b.Parameters[0]] = p;
Expression body = Expression.OrElse(a.Body, visitor.Visit(b.Body));
return Expression.Lambda>(body, p);
}
}
And the utility class to substitute the parameters in a lambda:
internal class SubstExpressionVisitor : System.Linq.Expressions.ExpressionVisitor {
public Dictionary subst = new Dictionary();
protected override Expression VisitParameter(ParameterExpression node) {
Expression newValue;
if (subst.TryGetValue(node, out newValue)) {
return newValue;
}
return node;
}
}