2010-11-09 221 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