Практическое руководство. Изменение деревьев выражений (Visual Basic)
В этом разделе показано, как изменить дерево выражения. Деревья выражений являются неизменяемыми, что означает невозможность их изменения напрямую. Чтобы изменить дерево выражения, необходимо создать копию существующего дерева выражения, а затем внести необходимые изменения. Для прохода по существующему дереву выражения и копирования каждого пройденного узла можно использовать класс ExpressionVisitor.
Изменение дерева выражения
Создайте новый проект консольного приложения.
Добавьте инструкцию
Imports
в файл дляSystem.Linq.Expressions
пространства имен.Добавьте в проект класс
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
, метод передает выполнение реализации базового класса. Методы базового класса создают узлы, которые похожи на переданные деревья выражений, однако поддеревья этих деревьев заменены на деревья выражений, которые были рекурсивно созданы при обходе.Добавьте инструкцию
Imports
в файл дляSystem.Linq.Expressions
пространства имен.Добавьте код в
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
этого класса передается выражение. Как исходные, так и измененные деревья выражений выводятся для отображения изменения.Скомпилируйте и запустите приложение.
См. также
- Практическое руководство. Выполнение деревьев выражений (Visual Basic)
- Expression Trees (Visual Basic) (Деревья выражений (Visual Basic))