7

System.Linq.Expressions.ExpressionVisitor有一个名为的方法,除了调用被访问的方法VisitExtension外,它似乎什么也不做。VisitChildrenExpression

protected internal virtual Expression VisitExtension(Expression node)
{
    return node.VisitChildren(this);
}

我明白它的VisitChildren作用。我也明白这个虚拟实现可以并且可能意味着被覆盖。因此,我从MSDN 上的方法文档中收集了一些信息,并简要说明了这一点:

访问扩展表达式的子级。这可以被覆盖以访问或重写特定的扩展节点。如果它没有被覆盖,这个方法将调用 VisitChildren,这让节点有机会遍历它的子节点。默认情况下,VisitChildren 将尝试减少节点。

我觉得这个解释没有帮助。具体来说,让我无法理解的短语是“或重写特定的扩展节点”。

我理解它的其余部分,这与将表达式简化或分解为子表达式有关。

在同一个命名空间中还有一个名为 的枚举ExpressionType,我非常了解它的目的。但是在它的所有成员中,有一个名为Extension我无法映射到我目前知道的任何语法标记的成员。

例中的文档也非常简洁。它描述的值Extension如下:

扩展表达式。

很明显,这两者 -ExpressionType.ExtensionExpressionVisitor.VisitExtension- 是相关的。

但是什么是扩展?当然,正如显而易见的那样,扩展方法在这种情况下没有地位。表达式扩展在这里指的是哪个语法工件?

4

1 回答 1

13

在这种情况下,扩展不代表任何类型的内置语法,而是对应于应用程序可以定义和分配任意含义的节点。

当在应用程序中操作表达式树时,该概念非常有用,因为这些扩展节点可以完全集成到正常的表达式树中。

例如,我定义了System.Linq.Expressions.Expressionwith 节点类型的子类,ExpressionType.Extension以扩展 Entity Framework 的 LINQ 以了解我公司使用的复合主键的类型。

扩展表达式类型很有用,因为它让我可以使用两步方法:

  • 在第一步中,表达式访问者会将复合键的每一次出现都规范化为我的自定义类型的节点;
  • 在第二步中,负责将表达式转换为实体框架能够处理的内容的表达式访问者可以简单地检查类型;

示例:假设我有编写的 LINQ 代码:

from e in table where e.FirstKey == e.SecondKey select e;

whereFirstKeySecondKeywere 都是复合数据库键(即,有两个数据库列FirstKey1FirstKey2for FirstKey,类似地 for SecondKey)。

然后第一个访问者会将e.FirstKey和都转换e.SecondKeyCustomKeyExpression节点,在功能上将其转换为:

from e in table where Key(e.FirstKey1, e.FirstKey2) == Key(e.SecondKey1, e.SecondKey2) select e;

在第二个访问者中,当我访问 时EqualExpression,我会检查两个孩子都是CustomKeyExpressions,并进行适当的转换:

from e in table where e.FirstKey1 == e.SecondKey1 && e.FirstKey2 == e.SecondKey2;
于 2014-12-16T13:58:10.533 回答