Поделиться через


Практическое руководство. Изменение деревьев выражений (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. Скомпилируйте и запустите приложение.

См. также