Lambda 到表达式树的转换
Posted
技术标签:
【中文标题】Lambda 到表达式树的转换【英文标题】:Lambda to Expression tree conversion 【发布时间】:2010-11-21 14:20:43 【问题描述】:我会保持简单,
如何从 lambda 中获取表达式树??
还是来自查询表达式?
【问题讨论】:
【参考方案1】:您必须将 lambda 分配给不同的类型:
// Gives you a delegate:
Func<int, int> f = x => x * 2;
// Gives you an expression tree:
Expression<Func<int, int>> g = x => x * 2;
方法参数也是如此。但是,一旦将这样的 lambda 表达式分配给 Func<>
类型,就无法取回表达式树。
【讨论】:
在第一种情况下,Delegate 是比 lambda 更好的术语。两者都是 lambda 表达式,一个隐式转换为匿名委托,另一个是表达式树。 @nawfalf
是代表。但是x => x * 2
是一个 lambda 表达式(正如您自己指出的那样)。你的评论暗示我说了一些不同的东西,但我真的没有。
你说第二个表达式给你一个表达式树。与此类似,第一个 lambda 表达式应该给你一个委托,而不是一个 lambda - 这是你的第一条评论。不吹毛求疵,只是提一下,以便将来对某人有所帮助。
@KonradRudolph,感谢您的提示。我想了解为什么x => x * 2
可以同时分配给Func<int,int>
和Expression<Func<int,int>>
? x => x * 2
的 CLR 类型是什么?这是否意味着Func<int,int>
和Expression<Func<int,int>>
派生自同一个基类型?
@KFL,lambda 表达式本身是您作为程序代码键入的表达式,不一定对应于特定类型。 Func<a, b>
和 Expression<Func<a, b>>
不必从相同的基类型派生,当您说 int x = 42
和 float y = 42
时,int
和 float
不必从相同的基类型派生【参考方案2】:
康拉德的回答是准确的。您需要将 lambda 表达式分配给 Expression<Func<...>>
,以便编译器生成表达式树。如果你得到一个 Func<...>
、Action<...>
或其他委托类型的 lambda,那么你所拥有的只是一堆 IL 指令。
如果您确实需要能够将 IL 编译的 lambda 转换回表达式树,则必须对其进行反编译(例如,执行 Lutz Roeder 的 Reflector 工具所做的事情)。我建议您查看Cecil 库,它提供了高级 IL 操作支持,可以为您节省相当多的时间。
【讨论】:
【参考方案3】:只是为了扩展 Konrad 的答案并纠正 Pierre,您仍然可以从 IL 编译的 lambda 生成表达式,尽管它不是非常优雅。扩充康拉德的例子:
// Gives you a lambda:
Func<int, int> f = x => x * 2;
// Gives you an expression tree:
Expression<Func<int, int>> g = x => f(x);
【讨论】:
这不给你原始lamda的表达式树,它给你一个调用委托的new表达式树。仅此而已。 这个问题并不特定于获得 equivalent 表达式。对于内存中的 LINQ,这提供了相同的功能。当然,任何 LINQ 提供程序都无法正确解析它。以上是关于Lambda 到表达式树的转换的主要内容,如果未能解决你的问题,请参考以下文章
C# 表达式树 创建生成使用lambda转成表达式树~表达式树的知识详解
基于Expression Lambda表达式树的通用复杂动态查询构建器——《剧透一下》