【问题标题】:How do I call methods with reference variables with Expression Trees如何使用表达式树调用具有引用变量的方法
【发布时间】:2013-02-18 15:54:01
【问题描述】:

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

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

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

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

    {
        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()();
    }

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

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

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

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

Type.MakeByRefType()

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

        {
        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()();
    }

【问题讨论】:

  • 您是否尝试过使用 lambda 表达式调用相同的方法,让 C# 编译器将其转换为表达式树,然后反编译?这通常是我研究如何构建表达式树的方法:)
  • 不,我以前没做过。任何通过示例的网址?

标签: c# .net expression-trees


【解决方案1】:

您不必进行太多更改,只需删除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
);

【讨论】:

  • 不记得我的头顶,但是可以在这里使用(半未记录的)__makeref 关键字吗?当然,您需要一个实际变量。
  • @JerKimball 正如你所说,__makeref 作用于变量,而不是类型,所以我们不能在这里使用它。请注意,MakeByRefType 部分仅由GetMethod 用于解决TwiceTheInputByRef 的适当重载:如果没有重载,则第二个参数是多余的。
  • Type.MakeByRefType() 是否同样适用于 ref 和 out 参数? (它似乎在我尝试过的快速测试中起作用..)
  • 是的,out 参数是“by ref”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-05
  • 1970-01-01
  • 2015-09-12
相关资源
最近更新 更多