Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace a parameter in an expression with a constant

I have an expression of type Expression<Func<TElement, TElement, bool>> and a constant of type TElement. I need an expression of type Expression<Func<TElement, bool>> with one of the parameters replaced by the constant. In other words, I need the body to the following method:

public static Expression<Func<TElement, bool>> ReplaceParameter<TElement>
(
    Expression<Func<TElement, TElement, bool>> inputExpression,
    TElement element
)
{
    ...
}

If I call ReplaceParameter((i1, i2) => i1 > i2, 5), I expect the result to be i => i > 5.

I was thinking, it might be able to recursively deconstruct and then reconstruct the input expression and replace all occurrences of the second parameter with a constant expression. Since there are so many different kind of expressions, I'm unsure on how to do that, though.

like image 861
Tim Pohlmann Avatar asked Feb 28 '26 08:02

Tim Pohlmann


1 Answers

ExpressionVisitor is your friend:

static void Main()
{
    Expression<Func<int, int, bool>> before = (x, y) => x * 2 == y + 1;
    var after = ReplaceParameter(before, 3);
    Console.WriteLine(after);
}
public static Expression<Func<TElement, bool>> ReplaceParameter<TElement>
(
    Expression<Func<TElement, TElement, bool>> inputExpression,
    TElement element
)
{
    var replacer = new Replacer(inputExpression.Parameters[0],
        Expression.Constant(element, typeof(TElement)));
    var body = replacer.Visit(inputExpression.Body);
    return Expression.Lambda<Func<TElement, bool>>(body,
        inputExpression.Parameters[1]);
}
class Replacer : ExpressionVisitor
{
    private readonly Expression _from, _to;
    public Replacer(Expression from, Expression to)
    {
        _from = from;
        _to = to;
    }
    public override Expression Visit(Expression node)
        => node == _from ? _to : base.Visit(node);
}

Note that this does not automatically collapse pure constant expressions, i.e. the code shown results in:

y => ((3 * 2) == (y + 1))

You could however, if you wanted, try looking for BinaryExpression that only has ConstantExpression as inputs, and evaluate the node directly, again inside Replacer.

like image 122
Marc Gravell Avatar answered Mar 03 '26 13:03

Marc Gravell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!