using System.Collections.Generic;
using System.Linq.Expressions;
public static class Program
public static void Main()
HireDate = new DateTime(2017, 1, 1)
HireDate = new DateTime(2014, 12, 31)
HireDate = new DateTime(2017, 1, 1)
HireDate = new DateTime(2017, 1, 1)
var rules = new RuleGroup(new List<Rule>
new RuleGroup(new List<Rule>
new RulePrimitive("Name", ExpressionType.Equal, "gary"),
new RulePrimitive("Name", ExpressionType.Equal, "spencer")
}, ExpressionType.OrElse),
new RulePrimitive("HireDate", ExpressionType.GreaterThan, new DateTime(2015, 1, 1))
}, ExpressionType.AndAlso);
var filteredEmployees = employees.WhereRules(rules);
foreach (var emp in filteredEmployees)
Console.WriteLine("{0} - {1:d}", emp.Name, emp.HireDate);
public abstract class Rule
public abstract Expression BuildExpression(ParameterExpression parameter);
public class RulePrimitive : Rule
public string PropertyName { get; set; }
public ExpressionType Operation { get; set; }
public object Value { get; set; }
public RulePrimitive(string propertyName, ExpressionType operation, object value)
PropertyName = propertyName;
public override Expression BuildExpression(ParameterExpression parameter)
var left = Expression.Property(parameter, PropertyName);
var right = Expression.Constant(Value);
return Expression.MakeBinary(Operation, left, right);
public class RuleGroup : Rule
public List<Rule> SubRules { get; set; }
public ExpressionType CombineWith { get; set; }
public RuleGroup(List<Rule> subRules, ExpressionType combineWith)
CombineWith = combineWith;
public override Expression BuildExpression(ParameterExpression parameter)
var expressions = SubRules.Select(rule => rule.BuildExpression(parameter));
var combined = expressions.Aggregate((left, right) => Expression.MakeBinary(CombineWith, left, right));
public static class EnumerableExtensions
public static IEnumerable<T> WhereRules<T>(this IEnumerable<T> source, Rule rule)
var parameter = Expression.Parameter(typeof(T), "x");
var expression = rule.BuildExpression(parameter);
var lambda = Expression.Lambda<Func<T, bool>>(expression, parameter);
Console.WriteLine(lambda);
var compiled = lambda.Compile();
return source.Where(compiled);
public string Name { get; set; }
public DateTime HireDate { get; set; }