2010-11-09 119 views
3

我希望能夠建立類似下面的委託表達式:如何在「sub」表達式中使用lambda表達式參數?

Func<object[], object> createSomeType1 = (args) => 
{ 
    return new SomeType1((P1)args[0], (P2)args[1], (P3)args[2]); 
}; 

我剛開始學習手工製作的表達式,所以原諒我,如果這是一個相當簡單的問題(或者說我誤解東西)。

我知道,創建具有正確類型的構造,我會做到以下幾點:

var p1 = Expression.Parameter(typeof(P1)); 
var p2 = Expression.Parameter(typeof(P2)); 
var p3 = Expression.Parameter(typeof(P3)); 
var someType1Exp = Expression.New(constructorInfo, p1, p2, p3); 

然後我知道了「外」拉姆達是,我認爲,聲明如下:

Expression<Func<object[], object>>.Lambda<Func<object[], object>>(
      someType1Exp, 
      Expression.Parameter(typeof(object[]))); 

我在包裝我的頭時遇到了麻煩,如何從外部表達式將參數「傳遞」到內部表達式,然後將其轉換爲正確的類型。

任何暗示正確的方向表示讚賞。

+1

添加完整的示例使用內部/外部lambd一個;實際上你並不需要這麼做 - 你可以直接在一個lambda中做。 – 2010-11-09 21:09:24

回答

2

我在iPod,因此目前不能給一個完整的例子:但:

  • 聲明類型的對象[](Expression.Param(typeof(object[])))的PARAM並存儲在一個變量
  • 用於從所述陣列中的每個術語,使用數組索引以獲得對索引的表達式,以及「Convert」或「鑄造」(iPod的再次!)投它
  • 使用Expression.Invoke,使內表達加索引+施放你以上生成的

我會很樂意這樣做後,如果您需要(當我在一臺PC)


完整的示例一個完整的例子:

Type[] types = new Type[] { typeof(int), typeof(float), typeof(string) }; 

var constructorInfo = typeof(SomeType).GetConstructor(types); 
var parameters = types.Select((t,i) => Expression.Parameter(t, "p" + i)).ToArray(); 
var someType1Exp = Expression.New(constructorInfo, parameters); 
var inner = Expression.Lambda(someType1Exp, parameters); 

var args = Expression.Parameter(typeof(object[]), "args");   
var body = Expression.Invoke(inner, 
    parameters.Select((p,i) => Expression.Convert(Expression.ArrayIndex(args, Expression.Constant(i)), p.Type)).ToArray()); 
var outer = Expression.Lambda<Func<object[], object>>(body, args); 
var func = outer.Compile(); 

object[] values = {1, 123.45F, "abc"}; 
object obj = func(values); 
Console.WriteLine(obj); 

或者作爲單個表達式:

Type[] types = new Type[] { typeof(int), typeof(float), typeof(string) }; 
var constructorInfo = typeof(SomeType).GetConstructor(types); 

var args = Expression.Parameter(typeof(object[]), "args");   
var body = Expression.New(constructorInfo, 
    types.Select((t,i) => Expression.Convert(Expression.ArrayIndex(args, Expression.Constant(i)), t)).ToArray()); 
var outer = Expression.Lambda<Func<object[], object>>(body, args); 
var func = outer.Compile(); 

object[] values = {1, 123.45F, "abc"}; 
object obj = func(values); 
Console.WriteLine(obj); 
+0

感謝您的回覆。當你有時間時,你能提供一個例子嗎?我絆倒第二顆子彈......乾杯! – TheCloudlessSky 2010-11-09 16:18:32

+0

@TheCloudlessSky我會稍後;但你也使用反射器來查看錶達式<< object [],Foo >> f = arr => SomeFunc((Type1)arr [0],...); – 2010-11-09 16:29:15

+0

我應該意識到反射器會顯示我想要的。我會看看並讓你知道它是如何發展的。謝謝! – TheCloudlessSky 2010-11-09 16:38:30