title: C# Pass expression as argument and use PredicateBuilder
body: <p>I want to dynamically build LinqToSQL and EntityFramework query clauses using a "criteria" object and if necessary leveraging the C# In a Nutshell PredicateBuilder (<a href="http://www.albahari.com/nutshell/predicatebuilder.aspx" rel="nofollow">http://www.albahari.com/nutshell/predicatebuilder.aspx</a>)</p>
  
  <p>Just to be clear - I don't understand how to create C# expressions ;o)</p>
  
  <p>The filter operator and value are defined as a property of my "query criteria" class as such:</p>
  
  <pre><code>public class QueryCriteria
  {
      public DateTimeFilter DateTimeCompleted { get; set; }
  }
  </code></pre>
  
  <p>The "filter" defined as:</p>
  
  <pre><code>public class DateTimeFilter
  {
      public FilterOperator FilterOperator { get; set; }
  
      public DateTime FilterToken { get; set; }
  }
  </code></pre>
  
  <p>And the "filter operator" is a plain C# enum:</p>
  
  <pre><code>public enum FilterOperator : int
  {
      ExactMatch = 1,
      BeginsWith = 2,
      Contains = 3,
      EndsWith = 4,
      GreaterThan = 5,
      GreaterThanOrEqualTo = 6,
      LessThan = 7,
      LessThanOrEqualTo = 8,
  }
  </code></pre>
  
  <p>I want to dynamically build my LinqToSQL and EntityFramework queries in my repositories using an approach such as:</p>
  
  <pre><code>if (criteria.DateTimeCompleted != null)
  {
      var predicate = PredicateBuilder.True(query);
  
      switch (criteria.DateTimeCompleted.FilterOperator)
      {
          case FilterOperator.ExactMatch:
              predicate = predicate.And(p =&gt; string.Equals(p.DateTimeCompleted.Value, criteria.DateTimeCompleted.FilterToken));
              break;
  
          case FilterOperator.GreaterThan:
              predicate = predicate.And(p =&gt; p.DateTimeCompleted.Value &gt; criteria.DateTimeCompleted.FilterToken);
              break;
  
          case FilterOperator.GreaterThanOrEqualTo:
              predicate = predicate.And(p =&gt; p.DateTimeCompleted.Value &gt;= criteria.DateTimeCompleted.FilterToken);
              break;
  
          case FilterOperator.LessThan:
              predicate = predicate.And(p =&gt; p.DateTimeCompleted.Value &lt; criteria.DateTimeCompleted.FilterToken);
              break;
  
          case FilterOperator.LessThanOrEqualTo:
              predicate = predicate.And(p =&gt; p.DateTimeCompleted.Value &lt;= criteria.DateTimeCompleted.FilterToken);
              break;
  
          default:
              throw new InvalidOperationException("Can't use the specified filter operator on a DateTime.");
      }
  
      query = query.Where(predicate);
  }
  </code></pre>
  
  <p>The above all works but I want my code to be DRY and when I add another property to my criteria (e.g. DateTimeStarted) I don't want my repository to duplicate the code immediately above for the new property.</p>
  
  <p>So I want to simplify the above code to something like:</p>
  
  <pre><code>query = query.Where(criteria.DateTimeCompleted.GetPredicate(query, p =&gt; p.DateTimeCompleted.Value));
  </code></pre>
  
  <p>Is this possible and if so how?</p>