我正在动态创建一个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
部分。我怎样才能解决这个问题?
答案 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