2011-12-14 77 views
7

如果我想創建一個調用out參數的方法的表達式樹,然後返回out值作爲結果..我該如何去解決它?ByRef參數與C#中的表達式樹

下不起作用(拋出一個運行時異常),但也許最能反映我想要做的事:

private delegate void MyDelegate(out int value); 
private static Func<int> Wrap(MyDelegate dele) 
{ 
    MethodInfo fn = dele.Method; 
    ParameterExpression result = ParameterExpression.Variable(typeof(int)); 
    BlockExpression block = BlockExpression.Block(
     typeof(int), // block result 
     Expression.Call(fn, result), // hopefully result is coerced to a reference 
     result); // return the variable 
    return Expression.Lambda<Func<int>>(block).Compile(); 
} 

private static void TestFunction(out int value) 
{ 
    value = 1; 
} 

private static void Test() 
{ 
    Debug.Assert(Wrap(TestFunction)() == 1); 
} 

我知道這可以用原始IL相當容易解決的(或不確實運行時編譯),但不幸的是,這是一個更大的表達式構建過程的一部分......所以我真的希望這不是一個限制,因爲完全重寫將不僅僅是一個痛苦。

+1

Lambda函數當然可以調用具有`ref` /`out`參數的方法(如有問題),他們不能做的是引用封閉方法的`ref` /`out`參數。 – Mania 2011-12-14 13:44:02

回答

7

這個工作對我來說:

private static Func<int> Wrap(MyDelegate dele) 
    { 
     var fn = dele.Method; 
     var result = ParameterExpression.Variable(typeof(int)); 
     var block = BlockExpression.Block(
      typeof(int), 
      new[] { result }, 
      new Expression[] 
      { 
       Expression.Call(fn, result), 
       result, 
      }); 
     return Expression.Lambda<Func<int>>(block).Compile(); 
    } 
-4

也許這只是我,但我實在不明白整個事情的地步。要完成你想要做的事情,你並不需要編寫所有這些東西。

示例代碼在一個控制檯應用程序:

class Program 
    { 
     static void Main(string[] args) 
     { 
      var temp = Execute(DoSomething); 
      Console.Write(temp); 
      Console.Read(); 
     } 

     static int Execute(Func<int> methodToRun) 
     { 
      return methodToRun.Invoke(); 
     } 

     static int DoSomething() 
     { 
      return 1; 
     } 
    } 

正如你看到它可以讓你在一個更簡潔和乾淨的方式相同的結果。我認爲你錯過的是Action,Action<>Func<>都是delegate的所有sinto糖,所以不需要混合2種語法,也不需要像你在做的那樣重構整個表達式。

+0

練習的要點是生成運行時代碼。也就是說,如果你傳遞了一個完全隨意的`MethodInfo`,並希望能夠以最小的性能損失來旋轉結果/參數。你不能直接調用該方法,因爲在編譯時你不知道它的細節,你可以使用反射來在運行時調用該方法,但這會很慢.. Expression.Compile允許你做一個第一次做更多的工作,但創建一種方法可以讓您以最低的成本重複執行,以便將來調用。這就是要點;) – Mania 2011-12-14 13:38:49