Created
October 9, 2015 23:53
-
-
Save WiredUK/8f80e83dd742f6110f13 to your computer and use it in GitHub Desktop.
Logicizer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class Logicizer | |
{ | |
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> leftExpression, Expression<Func<T, bool>> rightExpression) | |
{ | |
var parameter = Expression.Parameter(typeof(T)); | |
var left = new ReplaceExpressionVisitor(leftExpression.Parameters[0], parameter) | |
.Visit(leftExpression.Body); | |
var right = new ReplaceExpressionVisitor(rightExpression.Parameters[0], parameter) | |
.Visit(rightExpression.Body); | |
return Expression.Lambda<Func<T, bool>>(Expression.And(left, right), parameter); | |
} | |
public static Expression<Func<T, bool>> Or<T>(params Expression<Func<T, bool>>[] expressions) | |
{ | |
if(expressions.Length < 2) | |
throw new ArgumentException("Must have at least 2 expressions"); | |
if (expressions.Length > 2) | |
return Or<T>(expressions[0], Or<T>(expressions.Skip(1).ToArray())); | |
var parameter = Expression.Parameter(typeof(T)); | |
var left = new ReplaceExpressionVisitor(expressions[0].Parameters[0], parameter) | |
.Visit(expressions[0].Body); | |
var right = new ReplaceExpressionVisitor(expressions[1].Parameters[0], parameter) | |
.Visit(expressions[1].Body); | |
return Expression.Lambda<Func<T, bool>>(Expression.Or(left, right), parameter); | |
} | |
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expression) | |
{ | |
var parameter = Expression.Parameter(typeof(T)); | |
var expressionVisitor = new ReplaceExpressionVisitor(expression.Parameters[0], parameter) | |
.Visit(expression.Body); | |
return Expression.Lambda<Func<T, bool>>(Expression.Not(expressionVisitor), parameter); | |
} | |
} | |
internal class ReplaceExpressionVisitor : ExpressionVisitor | |
{ | |
private readonly Expression _oldValue; | |
private readonly Expression _newValue; | |
public ReplaceExpressionVisitor(Expression oldValue, Expression newValue) | |
{ | |
_oldValue = oldValue; | |
_newValue = newValue; | |
} | |
public override Expression Visit(Expression node) | |
{ | |
return node == _oldValue ? _newValue : base.Visit(node); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Some helper methods to provide And/Or/Not operation on generic expressions. Done like this means they are also compatible with Entity Framework. So for example you can do this:
And Entity Framework will generate a SQL query something like this: