Skip to content

Commit

Permalink
fix: use expression visitors
Browse files Browse the repository at this point in the history
  • Loading branch information
melflitty-aneo committed Jul 31, 2023
1 parent d8cafd6 commit b6ae04f
Showing 1 changed file with 48 additions and 8 deletions.
56 changes: 48 additions & 8 deletions Common/src/gRPC/ExpressionExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,21 @@ public static class ExpressionExt
/// <returns> A new predicate expression that represents the logical AND of the two expressions </returns>
public static Expression<Func<T, bool>> ExpressionAnd<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
=> Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body,
Expression.Invoke(expr2,
expr1.Parameters)),
expr1.Parameters);
{
var parameter = Expression.Parameter(typeof(T));

var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0],
parameter);
var left = leftVisitor.Visit(expr1.Body);

var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0],
parameter);
var right = rightVisitor.Visit(expr2.Body);

return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(left,
right),
parameter);
}

/// <summary>
/// Combines two predicate expressions using a logical OR condition
Expand All @@ -45,8 +56,37 @@ public static Expression<Func<T, bool>> ExpressionAnd<T>(this Expression<Func<T,
/// <returns> A new predicate expression that represents the logical OR of the two expressions </returns>
public static Expression<Func<T, bool>> ExpressionOr<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
=> Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body,
Expression.Invoke(expr2,
expr1.Parameters)),
expr1.Parameters);
{
var parameter = Expression.Parameter(typeof(T));

var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0],
parameter);
var left = leftVisitor.Visit(expr1.Body);

var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0],
parameter);
var right = rightVisitor.Visit(expr2.Body);

return Expression.Lambda<Func<T, bool>>(Expression.OrElse(left,
right),
parameter);
}

private class ReplaceExpressionVisitor : ExpressionVisitor
{
private readonly Expression newValue_;
private readonly Expression oldValue_;

public ReplaceExpressionVisitor(Expression oldValue,
Expression newValue)
{
oldValue_ = oldValue;
newValue_ = newValue;
}

public override Expression Visit(Expression node)
=> node == oldValue_
? newValue_
: base.Visit(node);
}
}

0 comments on commit b6ae04f

Please sign in to comment.