Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I call methods with reference variables with Expression Trees

I am trying to figure out how to create an Expression that calls a method which has a reference parameter.

Let me explain my question with a simple (but artificial) example. Consider the method:

    public static int TwiceTheInput(int x)
    {
        return x*2;
    }

I can create an Expression to call the above method by doing something like:

    {
        var inputVar = Expression.Variable(typeof (int), "input");
        var blockExp =
            Expression.Block(
                    new[] {inputVar}
                    , Expression.Assign(inputVar, Expression.Constant(10))
                    , Expression.Assign(inputVar, Expression.Call(GetType().GetMethod("TwiceTheInput", new[] { typeof(int) }), inputVar))
                    , inputVar
                    );
        var result = Expression.Lambda<Func<int>>(blockExp).Compile()();
    }

On execution, the "result" above should end up with a value of 20. Now consider a version of TwiceTheInput() that uses by-reference parameters:

    public static void TwiceTheInputByRef(ref int x)
    {
        x = x * 2;
    }

How do I write a similar Expression Tree to call TwiceTheInputByRef() and pass arguments by reference to it?

Solution: (Thanks to Cicada). Use:

Type.MakeByRefType()

Here's a code segment to generate the Expression Tree:

        {
        var inputVar = Expression.Variable(typeof(int), "input");
        var blockExp =
            Expression.Block(
                    new[] { inputVar }
                    , Expression.Assign(inputVar, Expression.Constant(10))
                    , Expression.Call(GetType().GetMethod("TwiceTheInputByRef", new[] { typeof(int).MakeByRefType() }), inputVar)
                    , inputVar
                    );
        var result = Expression.Lambda<Func<int>>(blockExp).Compile()();
    }
like image 249
DPrb Avatar asked Feb 18 '13 15:02

DPrb


People also ask

Can you have an expression in a method call?

A method call expression produces the pure value returned by the method; the type of this value is specified by the return type in the method declaration. But if the method has the return type void, the expression does not produce a value.

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.

What is the role of expression trees in LINQ?

You can compile and run code represented by expression trees. This enables dynamic modification of executable code, the execution of LINQ queries in various databases, and the creation of dynamic queries. For more information about expression trees in LINQ, see How to use expression trees to build dynamic queries (C#).

What is expression tree give example?

Each node in an expression tree is an expression. For example, an expression tree can be used to represent mathematical formula x < y where x, < and y will be represented as an expression and arranged in the tree like structure. Expression tree is an in-memory representation of a lambda expression.


1 Answers

You don't have to change much, just remove the Assign and change typeof(int) to typeof(int).MakeByRefType().

var blockExp = Expression.Block(
    new[] { inputVar }
    , Expression.Assign(inputVar, Expression.Constant(10))
    , Expression.Call(
       typeof(Program).GetMethod( 
           "TwiceTheInputByRef", new [] { typeof(int).MakeByRefType() }),
       inputVar)
    , inputVar
);
like image 52
user703016 Avatar answered Oct 12 '22 10:10

user703016