Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Well, you can use <code>Expression.AndAlso</code> / <code>OrElse</code> etc to combine logical expressions, but the problem is the parameters; are you working with the same <code>ParameterExpression</code> in expr1 and expr2? If so, it is easier:</p> <pre><code>var body = Expression.AndAlso(expr1.Body, expr2.Body); var lambda = Expression.Lambda&lt;Func&lt;T,bool&gt;&gt;(body, expr1.Parameters[0]); </code></pre> <p>This also works well to negate a single operation:</p> <pre><code>static Expression&lt;Func&lt;T, bool&gt;&gt; Not&lt;T&gt;( this Expression&lt;Func&lt;T, bool&gt;&gt; expr) { return Expression.Lambda&lt;Func&lt;T, bool&gt;&gt;( Expression.Not(expr.Body), expr.Parameters[0]); } </code></pre> <p>Otherwise, depending on the LINQ provider, you might be able to combine them with <code>Invoke</code>:</p> <pre><code>// OrElse is very similar... static Expression&lt;Func&lt;T, bool&gt;&gt; AndAlso&lt;T&gt;( this Expression&lt;Func&lt;T, bool&gt;&gt; left, Expression&lt;Func&lt;T, bool&gt;&gt; right) { var param = Expression.Parameter(typeof(T), "x"); var body = Expression.AndAlso( Expression.Invoke(left, param), Expression.Invoke(right, param) ); var lambda = Expression.Lambda&lt;Func&lt;T, bool&gt;&gt;(body, param); return lambda; } </code></pre> <p>Somewhere, I have got some code that re-writes an expression-tree replacing nodes to remove the need for <code>Invoke</code>, but it is quite lengthy (and I can't remember where I left it...)</p> <hr> <p>Generalized version that picks the simplest route:</p> <pre><code>static Expression&lt;Func&lt;T, bool&gt;&gt; AndAlso&lt;T&gt;( this Expression&lt;Func&lt;T, bool&gt;&gt; expr1, Expression&lt;Func&lt;T, bool&gt;&gt; expr2) { // need to detect whether they use the same // parameter instance; if not, they need fixing ParameterExpression param = expr1.Parameters[0]; if (ReferenceEquals(param, expr2.Parameters[0])) { // simple version return Expression.Lambda&lt;Func&lt;T, bool&gt;&gt;( Expression.AndAlso(expr1.Body, expr2.Body), param); } // otherwise, keep expr1 "as is" and invoke expr2 return Expression.Lambda&lt;Func&lt;T, bool&gt;&gt;( Expression.AndAlso( expr1.Body, Expression.Invoke(expr2, param)), param); } </code></pre> <p>Starting from .net 4.0. There is the ExpressionVistor class which allows you to build expressions that are EF safe.</p> <pre><code> public static Expression&lt;Func&lt;T, bool&gt;&gt; AndAlso&lt;T&gt;( this Expression&lt;Func&lt;T, bool&gt;&gt; expr1, Expression&lt;Func&lt;T, bool&gt;&gt; expr2) { var parameter = Expression.Parameter(typeof (T)); var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter); var left = leftVisitor.Visit(expr1.Body); var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter); var right = rightVisitor.Visit(expr2.Body); return Expression.Lambda&lt;Func&lt;T, bool&gt;&gt;( Expression.AndAlso(left, right), parameter); } private class ReplaceExpressionVisitor : ExpressionVisitor { private readonly Expression _oldValue; private readonly Expression _newValue; public ReplaceExpressionVisitor(Expression oldValue, Expression newValue) { _oldValue = oldValue; _newValue = newValue; } public override Expression Visit(Expression node) { if (node == _oldValue) return _newValue; return base.Visit(node); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload