如何:修改表达式树 (Visual Basic)

本主题演示如何修改表达式树。 表达式树是不可变的,这意味着不能直接修改它们。 若要更改表达式树,必须创建现有表达式树的副本,并在创建副本时进行所需的更改。 可以使用 ExpressionVisitor 该类遍历现有表达式树,并复制它访问的每个节点。

修改表达式树

  1. 创建新的 控制台应用程序 项目。

  2. 将Imports语句添加到System.Linq.Expressions命名空间的文件。

  3. 将 AndAlsoModifier 类添加到项目。

    Public Class AndAlsoModifier
        Inherits ExpressionVisitor
    
        Public Function Modify(ByVal expr As Expression) As Expression
            Return Visit(expr)
        End Function
    
        Protected Overrides Function VisitBinary(ByVal b As BinaryExpression) As Expression
            If b.NodeType = ExpressionType.AndAlso Then
                Dim left = Me.Visit(b.Left)
                Dim right = Me.Visit(b.Right)
    
                ' Make this binary expression an OrElse operation instead
                ' of an AndAlso operation.
                Return Expression.MakeBinary(ExpressionType.OrElse, left, right, _
                                             b.IsLiftedToNull, b.Method)
            End If
    
            Return MyBase.VisitBinary(b)
        End Function
    End Class
    

    此类继承 ExpressionVisitor 类,并且专用于修改表示条件 AND 运算的表达式。 它将这些操作从条件 AND 更改为条件 OR。 若要执行此操作,此类替代基类型的 VisitBinary 方法,因为条件 AND 表达式表示为二进制表达式。 在VisitBinary方法中,如果传递给它的表达式表示条件AND运算,则代码会构造一个新的表达式,其中包含条件OR运算符,而不是条件AND运算符。 如果传递给 VisitBinary 的表达式不表示条件 AND 操作,该方法将调用基类的实现。 基类方法构造类似于传入的表达式树的节点,但节点的子树已替换为访问者以递归方式生成的表达式树。

  4. 将Imports语句添加到System.Linq.Expressions命名空间的文件。

  5. 将代码添加到 Main Module1.vb 文件中的方法以创建表达式树,并将其传递给将修改它的方法。

    Dim expr As Expression(Of Func(Of String, Boolean)) = _
        Function(name) name.Length > 10 AndAlso name.StartsWith("G")
    
    Console.WriteLine(expr)
    
    Dim modifier As New AndAlsoModifier()
    Dim modifiedExpr = modifier.Modify(CType(expr, Expression))
    
    Console.WriteLine(modifiedExpr)
    
    ' This code produces the following output:
    ' name => ((name.Length > 10) && name.StartsWith("G"))
    ' name => ((name.Length > 10) || name.StartsWith("G"))
    

    该代码创建一个包含条件 AND 操作的表达式。 然后,它会创建类的 AndAlsoModifier 实例,并将表达式传递给 Modify 此类的方法。 输出原始表达式树和修改后的表达式树以显示更改。

  6. 编译并运行应用程序。

另请参阅