如何在“sub”表达式中使用lambda表达式参数?

时间:2010-11-09 15:51:58

标签: c# .net 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);

然后我知道“外部”lambda,我认为是这样声明的:

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

我无法绕过如何将参数从外部表达式“传递”到内部表达式然后将其转换为正确的类型。

赞赏任何正确方向的提示。

1 个答案:

答案 0 :(得分:3)

我在iPod上,所以现在不能给出一个完整的例子:但是:

  • 声明一个类型为object [](Expression.Param(typeof(object[])))的参数并将其存储在变量中
  • 对于数组中的每个术语,使用数组 indexer 获取索引器的表达式,并使用“Convert”或“cast”(再次使用iPod!)来表达它/ LI>
  • 使用Expression.Invoke,传递内部表达式加上上面生成的索引器+强制转换

如果您需要(我在电脑前),我会很乐意再做一个完整的例子


完整示例:

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);