title: Currying Expressions in C#
body: <p>I am trying to build up an expression tree that I can feed into Linq2SQL so that it will generate a nice clean query. My purpose is to build a filter that takes an arbitrary set of words to AND and NOT (or OR and NOT) together. Because I want to vary the fields that I search on I preferably want to compose a list of <code>Expresssion&lt;Func&lt;T, string, bool&gt;&gt;</code>'s together (where T is the entity I am operating on) by calling a variety of helper functions. Then I would receive an array of words and loop though them and build an <code>Expresssion&lt;Func&lt;T, bool&gt;&gt;</code> up (negating certain expressions where necessary) that I can eventually feed to a .Where statement.</p>
  
  <p>I have been using LINQKit <a href="http://www.albahari.com/nutshell/predicatebuilder.aspx" rel="noreferrer">PredicateBuilder</a> but this code deals with single parameter expressions. However, it has provided me with some groundwork for my own attempts. I am aiming to do something like this:</p>
  
  <pre><code>var e = (Expression&lt;Func&lt;Entity, string, bool&gt;&gt;)((p, w) =&gt; p.SomeField.ToLower().Contains(w));
  
  var words = new []{"amanda", "bob"};
  
  var expr = (Expression&lt;Func&lt;Entity, bool&gt;&gt;)(p =&gt; false);
  // building up an OR query
  foreach(var w in words) {
      var w1 = w;
  &gt;&gt;&gt;&gt;expr = Expression.Lambda&lt;Func&lt;Entity, bool&gt;&gt;(Expression.OrElse(expr.Body, (Expression&lt;Func&lt;Entity, bool&gt;&gt;)(p =&gt; e(p, w))));
  }
  
  var filteredEntities = table.Where(expr);
  </code></pre>
  
  <p>But since I am using Expressions the line marked by >>>> is obviously illegal (cannot do <code>e(p, w)</code> like I could for a function). So my question is how do I do the partial application of a single variable (the word) to expressions containing functions with multiple parameters?</p>
  
  <hr>
  
  <p>Okay, fiddled around in LINQPad and figured out a solution that works for me. <a href="https://stackoverflow.com/questions/3157905/convert-expressionfunct-t2-bool-to-expressionfunct2-bool-by-introducin">This question</a> got me there. I am pretty new to building up expression trees so I would appreciate (and upvote) any comments/answers with improvements or criticism.</p>
  
  <pre><code>// Some set of expressions to test against
  var expressions = new List&lt;Expression&lt;Func&lt;Entity, string, bool&gt;&gt;&gt;();
  expressions.Add((p, w) =&gt; p.FirstName.ToLower().Contains(w));
  expressions.Add((p, w) =&gt; p.LastName.ToLower().Contains(w));
  expressions.Add((p, w) =&gt; p.Department != null &amp;&amp; p.Department.Name.ToLower().Contains(w));
  
  var words = new []{"amanda", "bob"};
  var negs = new []{"smith"}; // exclude any entries including these words
  
  var isAndQuery = true; // negate for an OR query
  Expression&lt;Func&lt;Entity, bool&gt;&gt; posExpr = p =&gt; isAndQuery;
  
  var entityParameter = Expression.Parameter(typeof(Entity), null);
  
  // Build up the NOTs
  var negExpr = (Expression&lt;Func&lt;Entity, bool&gt;&gt;)(p =&gt; true);
  foreach(var w in negs) {
      var w1 = w;
      foreach(var e in expressions) {
          var andNot = Expression.Invoke(e, entityParameter, Expression.Constant(w1));
          negExpr = Expression.Lambda&lt;Func&lt;Entity, bool&gt;&gt;(Expression.AndAlso(negExpr.Body, Expression.Not(andNot)), entityParameter);
      }
  }
  
  // Build up the ANDs or ORs
  foreach(var w in words) {
      var w1 = w;
      var orExpr = (Expression&lt;Func&lt;Entity, bool&gt;&gt;)(p =&gt; false);
      foreach(var e in expressions) {
          var orElse = Expression.Invoke(e, entityParameter, Expression.Constant(w1));
          orExpr = Expression.Lambda&lt;Func&lt;Entity, bool&gt;&gt;(Expression.OrElse(orExpr.Body, orElse), entityParameter);
      }
      var orInvoked = Expression.Invoke(orExpr, posExpr.Parameters.Cast&lt;Expression&gt;());
      if(isAndQuery)
          posExpr = Expression.Lambda&lt;Func&lt;Entity, bool&gt;&gt;(Expression.AndAlso(posExpr.Body, orInvoked), entityParameter);
      else
          posExpr = Expression.Lambda&lt;Func&lt;Entity, bool&gt;&gt;(Expression.OrElse(posExpr.Body, orInvoked), entityParameter);
  }
  var posInvoked = Expression.Invoke(posExpr, posExpr.Parameters.Cast&lt;Expression&gt;());
  var finalExpr = Expression.Lambda&lt;Func&lt;Entity, bool&gt;&gt;(Expression.AndAlso(negExpr.Body, posInvoked), entityParameter);
  
  var filteredEntities = entities.Where(finalExpr);
  </code></pre>