如何使用带有表达式树的引用变量调用方法

DPr*_*Prb 5 .net c# expression-trees

我试图弄清楚如何创建一个表达式,该表达式调用具有引用参数的方法。

让我用一个简单(但人为)的例子解释我的问题。考虑以下方法:

    public static int TwiceTheInput(int x)
    {
        return x*2;
    }
Run Code Online (Sandbox Code Playgroud)

我可以通过执行以下操作来创建一个表达式来调用上述方法:

    {
        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()();
    }
Run Code Online (Sandbox Code Playgroud)

在执行时,上面的“结果”应该以20结束。现在考虑使用按引用参数的TwiceTheInput()版本:

    public static void TwiceTheInputByRef(ref int x)
    {
        x = x * 2;
    }
Run Code Online (Sandbox Code Playgroud)

如何编写类似的表达式树来调用TwiceTheInputByRef()并通过引用传递参数?

解决方案:(感谢蝉)。使用:

Type.MakeByRefType()
Run Code Online (Sandbox Code Playgroud)

这是生成表达式树的代码段:

        {
        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()();
    }
Run Code Online (Sandbox Code Playgroud)

use*_*016 8

您不必更改太多,只需删除Assign并更改typeof(int)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
);
Run Code Online (Sandbox Code Playgroud)