Skip to content

Instantly share code, notes, and snippets.

@Serg046
Last active December 20, 2022 16:01
Show Gist options
  • Save Serg046/502addfb00171065ce8c to your computer and use it in GitHub Desktop.
Save Serg046/502addfb00171065ce8c to your computer and use it in GitHub Desktop.
public static class ExpressionCombiner
{
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> leftExpr, Expression<Func<T, bool>> rightExpr)
{
return Join(leftExpr, rightExpr, Expression.And);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> leftExpr, Expression<Func<T, bool>> rightExpr)
{
return Join(leftExpr, rightExpr, Expression.Or);
}
public static Expression<Func<T, bool>> Join<T>(Expression<Func<T, bool>> leftExpr, Expression<Func<T, bool>> rightExpr,
Func<Expression, Expression, BinaryExpression> joinFunc)
{
if (leftExpr == null)
throw new NullReferenceException(nameof(leftExpr));
if (rightExpr == null)
throw new NullReferenceException(nameof(rightExpr));
var visitor = new ParameterUpdateVisitor(rightExpr.Parameters.First(), leftExpr.Parameters.First());
rightExpr = visitor.Visit(rightExpr) as Expression<Func<T, bool>>;
var binExp = joinFunc(leftExpr.Body, rightExpr.Body);
return Expression.Lambda<Func<T, bool>>(binExp, rightExpr.Parameters);
}
class ParameterUpdateVisitor : ExpressionVisitor
{
private readonly ParameterExpression _oldParameter;
private readonly ParameterExpression _newParameter;
public ParameterUpdateVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
{
_oldParameter = oldParameter;
_newParameter = newParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (object.ReferenceEquals(node, _oldParameter))
return _newParameter;
return base.VisitParameter(node);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment