【问题标题】:Expression tree emits runtime code?表达式树发出运行时代码?
【发布时间】:2012-03-16 18:06:09
【问题描述】:

当您在运行时构建表达式树时,没有代码 发出。这是一种在运行时表示 .NET 代码的方式...

好的...

现在假设我有这个代码:

    ParameterExpression p = Expression.Parameter (typeof (string), "s");
    MemberExpression stringLength = Expression.Property (p, "Length");
    ConstantExpression five = Expression.Constant (5);
    BinaryExpression comparison = Expression.LessThan (stringLength, five);
    Expression<Func<string, bool>> lambda= Expression.Lambda<Func<string, bool>> (comparison, p);

    Func<string, bool> runnable = lambda.Compile();

此代码不会在 IL 中?当然会的! (也许最后一行在编译之前不会发出代码......但我认为第一行会发出代码!)

那么我在这里保存什么?

好的,所以前 5 行确实发出了代码,而最后一行没有……大不了。

我错过了什么?可以让我看看全图吗?

【问题讨论】:

  • 当你调用compile时,表达式树被转换为IL(使用DynamicMethod)。
  • @leppie 和前 5 行不会在 IL 中?
  • 嗯,这是最初编译的普通代码。表达式没有 IL 的概念,它是一种抽象,可以发送到 IL,但没有要求这样做(例如,您可以发送自己的 x86 ASM 或 GPU 代码等)。
  • 你从哪里得到这个声明的?
  • 我认为他的意思是“结果委托的 IL 代码”而不是“创建表达式的 IL 代码”。

标签: c# .net-4.0 expression-trees


【解决方案1】:

使用表达式树,您可以构建一些代码的描述,而不是代码本身。 表达式树不应在编写“不应在编译时编译”的常规代码的上下文中使用。它们应该用在更动态的场景中。

您显示的表达式树将编译为:s.Length &lt; 5,然后您使用bool isStringSmallerThan5 = runnable("MyString") 调用runnable

表达式树的整个想法是它们描述一些代码并且可以在运行时编译。这意味着您可以执行以下操作:

BinaryExpression comparison = null;
if (lessThen)
{
    comparison = Expression.LessThan(stringLength, five);
}
else
{
    comparison = Expression.GreaterThan(stringLength, five);
}

现在您可以在运行时更改代码的行为!

表达式树的最大用途是它们可以由提供者解释。例如,Linq To Entities 使用表达式树并将它们编译为可以针对数据库运行的 SQL 代码。 LinqToXml 是表达式树的另一个示例。

这是一个很好的blog post 让你开始。

【讨论】:

  • 我可以看到我该怎么做 9000 如果在我的代码中如果我想让它动态地行动......
  • 你想要达到什么目的?表达式树主要用于 Linq 之类的东西。创建真正的动态代码不是主要场景。如果你有 '9000' 个不同的场景,你想如何支持它们?
  • 我明白了....你能举个小例子吗 linq 如何在最简单的查询中使用它?
  • 我添加了指向 MSDN 博客文章的链接。
【解决方案2】:

当您在方法中接收表达式树时,它们很有用,因为它们使您能够更复杂地使用表达式内容。如果您在方法中收到谓词,则可以针对目标运行它并检查结果。如果您收到表示表达式树的表达式树,您可以解析它并用它做一些有用的事情。一个例子是 LINQ,它利用了这么多地方,但在“Where”方法中的一个。捕获表达式树而不是 IL 可以相对直接地转换为 SQL,而不仅仅是执行完整的“选择”并针对具体化结果运行谓词。

【讨论】:

  • 谢谢,但我从“代码发射”的角度提出了我的问题......我在这里保存什么?如果我得到而不是谓词 - 一个表达式树 - 我仍然必须“编译”它......那我得到了什么?我不明白这一点(我知道有一个:))。
  • 恕我直言,关键是您拥有更“友好”的中间表示。但是你肯定必须在某个时候编译它。让我们看看比我聪明的人是否有更好的解释:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多