如何使用动态确定的Type作为Lambda <func <>&gt;?</func <>的参数

时间:2011-10-26 14:25:20

标签: dynamic lambda c#-3.0

我正在动态创建一个Lambda表达式(基于用户输入,但目前使用虚拟值进行概念验证),这种类型我只能在运行时知道。因此,我需要将T的{​​{1}}部分作为动态类型传递,因为直到运行时我才会知道类型(Func<T,TResult>始终是TResult

似乎我无法传递bool变量或使用带有泛型的Type。基本上我正在尝试做这样的事情:

typeof

但是,我不能将变量// (f => f.Baz == 1) Type theType = Type.GetType("Foo"); ParameterExpression pe = Expression.Parameter(theType, "f"); Expression left = Expression.Property(pe, theType.GetProperty("Baz")); Expression right = Expression.Constant(1); Expression expr = Expression.Equal(left, right); // This works fine but uses a hard-coded type, which I won't know until runtime: // var lambda = Expression.Lambda<Func<Foo,bool>>(expr, new ParameterExpression[] { pe }).Compile(); var lambda = Expression.Lambda<Func<theType, bool>>(expr, new ParameterExpression[] { pe }).Compile(); 用作Func的theType部分。我怎样才能解决这个问题?

1 个答案:

答案 0 :(得分:1)

不,你不能。

例如,在C#中,你不能:

Type t = typeof(int);
List<t> list = new List<t>(); 

object list = new List<t>(); 

除非您使用反射,否则您必须将列表放在object中,并且只能通过反射使用它。

因此,如果您愿意,可以将Func<>保存在object(或dynamic)中,但不能再保存。

你可以做的总是返回Func<object, bool>并将对象强制转换为lambda函数中的desidered类型(所以使用Expression.Convert(pe, theType));

或者您可以使用动态:

// lambda == Func<Foo, bool>
dynamic lamdba = Expression.Lambda(expr, new ParameterExpression[] { pe }).Compile();

bool res = lambda(myvalue);

// lambda == Func<Foo, bool>
Delegate lamdba = Expression.Lambda(expr, new ParameterExpression[] { pe }).Compile();
bool res = (bool)lambda2.DynamicInvoke(t);

要采取“不那么真实”的一些基准测试(在StopWatch.Ticks中,只查看它们的比例)(发布模式+开始无调试+一些无用的循环,以便它们“热”):

  236384685 dynamic
   56773593 Func<object, bool> + cast
10556024247 DynamicInvoke

作为一个音符,Func<Foo, bool>具有相同的速度,因此额外演员阵容中没有任何速度损失。

您可以在此处查看代码http://ideone.com/qhnVP3