Skip to content

Instantly share code, notes, and snippets.

@JakeGinnivan
Created October 3, 2012 03:09
Show Gist options
  • Select an option

  • Save JakeGinnivan/3824725 to your computer and use it in GitHub Desktop.

Select an option

Save JakeGinnivan/3824725 to your computer and use it in GitHub Desktop.
PredicateBuilder
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>()
{
return Expression.Lambda<Func<T, bool>>(Expression.Constant(true), Expression.Parameter(typeof(T)));
}
public static Expression<Func<T, bool>> False<T>()
{
return Expression.Lambda<Func<T, bool>>(Expression.Constant(false), Expression.Parameter(typeof(T)));
}
public static Expression<Func<T, bool>> OrElse<T>(this Expression<Func<T, bool>> self, Expression<Func<T, bool>> expression)
{
return Combine(self, expression, Expression.OrElse);
}
public static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> self, Expression<Func<T, bool>> expression)
{
return Combine(self, expression, Expression.AndAlso);
}
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> self)
{
CheckSelf(self);
var parameter = CreateParameterFrom(self);
return Expression.Lambda<Func<T, bool>>(
Expression.Not(RewriteLambdaBody(self, parameter)),
parameter);
}
static Expression<Func<T, bool>> Combine<T>(Expression<Func<T, bool>> self, Expression<Func<T, bool>> expression, Func<Expression, Expression, Expression> selector)
{
CheckSelfAndExpression(self, expression);
var parameter = CreateParameterFrom(self);
return Expression.Lambda<Func<T, bool>>(
selector(
RewriteLambdaBody(self, parameter),
RewriteLambdaBody(expression, parameter)),
parameter);
}
static Expression RewriteLambdaBody(LambdaExpression expression, ParameterExpression parameter)
{
return new ParameterRewriter(expression.Parameters[0], parameter).Visit(expression.Body);
}
class ParameterRewriter : ExpressionVisitor
{
readonly ParameterExpression candidate;
readonly ParameterExpression replacement;
public ParameterRewriter(ParameterExpression candidate, ParameterExpression replacement)
{
this.candidate = candidate;
this.replacement = replacement;
}
protected override Expression VisitParameter(ParameterExpression expression)
{
return ReferenceEquals(expression, candidate) ? replacement : expression;
}
}
static ParameterExpression CreateParameterFrom<T>(Expression<Func<T, bool>> left)
{
var template = left.Parameters[0];
return Expression.Parameter(template.Type, template.Name);
}
static void CheckSelf<T>(Expression<Func<T, bool>> self)
{
if (self == null)
throw new ArgumentNullException("self");
}
static void CheckSelfAndExpression<T>(Expression<Func<T, bool>> self, Expression<Func<T, bool>> expression)
{
if (self == null)
throw new ArgumentNullException("self");
if (expression == null)
throw new ArgumentNullException("expression");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment