title: How to create an Expression builder in .NET
body: <p>I have written some code to allow filtering of products on our website, and I am getting a pretty bad code smell. The user can select 1-* of these filters which means I need to be specific with the <code>WHERE</code> clause.</p>
  
  <p>I think I am looking for a way to build up a lambda expression, so for every filter I can 'modify' my <code>WHERE</code> clause - but I am not sure how to do this in .NET, and there must be a way.</p>
  
  <p>Code in its current state (effectively hardcoded, not dynamic, would be a pain to add more filter options).</p>
  
  <pre><code>public static class AgeGroups
  {
      public static Dictionary&lt;string, int&gt; Items = new Dictionary&lt;string, int&gt;(){
          { "Modern (Less than 10 years old)", 1 },
          { "Retro (10 - 20 years old)", 2 },
          { "Vintage(20 - 70 years old)", 3 },
          { "Antique(70+ years old)", 4 }
      };
  
      public static IQueryable&lt;ProductDTO&gt; FilterAgeByGroup(IQueryable&lt;ProductDTO&gt; query, List&lt;string&gt; filters)
      {
          var values = new List&lt;int&gt;();
          var currentYear = DateTime.UtcNow.Year;
          foreach (var key in filters)
          {
              var matchingValue = Items.TryGetValue(key, out int value);
  
              if (matchingValue)
              {
                  values.Add(value);
              }
          }
  
          if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 1 }))
          {
              query = query.Where(x =&gt; x.YearManufactured &gt;= currentYear - 10);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 2 }))
          {
              query = query.Where(x =&gt; x.YearManufactured &lt;= currentYear - 10 &amp;&amp; x.YearManufactured &gt;= currentYear - 20);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 3 }))
          {
              query = query.Where(x =&gt; x.YearManufactured &lt;= currentYear - 20 &amp;&amp; x.YearManufactured &gt;= currentYear - 70);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 4 }))
          {
              query = query.Where(x =&gt; x.YearManufactured &lt;= currentYear - 70);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 1, 2}))
          {
              query = query.Where(x =&gt; x.YearManufactured &gt;= currentYear - 20);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 1, 3 }))
          {
              query = query.Where(x =&gt; x.YearManufactured &gt;= currentYear - 10 || (x.YearManufactured &lt;= currentYear - 20 &amp;&amp; x.YearManufactured &gt;= currentYear - 70));
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 1, 4 }))
          {
              query = query.Where(x =&gt; x.YearManufactured &gt;= currentYear - 10 ||  x.YearManufactured &lt;= currentYear - 70);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 2, 3 }))
          {
              query = query.Where(x =&gt; x.YearManufactured &lt;= currentYear - 10 &amp;&amp; x.YearManufactured &gt;= currentYear - 70);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 2, 4 }))
          {
              query = query.Where(x =&gt; (x.YearManufactured &lt;= currentYear - 10 &amp;&amp; x.YearManufactured &gt;= currentYear - 20) 
                                       || x.YearManufactured &lt;= currentYear - 70);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 1, 2, 3 }))
          {
              query = query.Where(x =&gt; x.YearManufactured &gt;= currentYear - 70);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 1, 2, 4 }))
          {
              query = query.Where(x =&gt; x.YearManufactured &gt;= currentYear - 20 || x.YearManufactured &lt;= currentYear - 70);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 2, 3, 4}))
          {
              query = query.Where(x =&gt; x.YearManufactured &lt;= currentYear - 10);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 1, 3, 4}))
          {
              query = query.Where(x =&gt; x.YearManufactured &gt;= currentYear - 10 || x.YearManufactured &lt;= 20);
          }
          else if (Utility.EqualsIgnoringOrder(values, new List&lt;int&gt; { 1, 2, 3, 4 }))
          {
              // all
          }
          return query;
      }
  }
  </code></pre>