Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding parameter in Expression trees

I would like to know how to bind parameters to values within an expression tree

Something like

Expression<Func<String, String, bool>> e1 = (x,y) => x == y;

Then I would like to bind y, while preserving it as a single expression. A obvious attempt would be something like

Expresion<Func<String, bool>> e2 = x => e1(x, "Fixed Value Here");

But that would turn my expression into an Invoke node. Is there a way to simply bind a parameter within my first expression while getting the signature of the second expression?

like image 339
Spooles Avatar asked Dec 22 '11 22:12

Spooles


People also ask

How does an expression tree work?

Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as x < y . You can compile and run code represented by expression trees.

What are the advantages of expression tree?

Expression trees allow you to build code dynamically at runtime instead of statically typing it in the IDE and using a compiler. They are well explained in the documentation.

When programmatically creating expression tree nodes what base class do you use?

Expression Class (System. Provides the base class from which the classes that represent expression tree nodes are derived. It also contains static (Shared in Visual Basic) factory methods to create the various node types. This is an abstract class.


1 Answers

Expression<Func<String, String, bool>> e1 = (x,y) => x == y;

var swap = new ExpressionSubstitute(e1.Parameters[1],
    Expression.Constant("Fixed Value Here"));
var lambda = Expression.Lambda<Func<string, bool>>(
    swap.Visit(e1.Body), e1.Parameters[0]);

with

class ExpressionSubstitute : ExpressionVisitor
{
    public readonly Expression from, to;
    public ExpressionSubstitute(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        if (node == from) return to;
        return base.Visit(node);
    }
}

this uses ExpressionVisitor to rebuild the expression, substituting y with the constant.

Another approach is to use Expression.Invoke, but this doesn't work in all cases.

like image 82
Marc Gravell Avatar answered Nov 05 '22 23:11

Marc Gravell