Procedura: modificare strutture ad albero dell'espressione (C# e Visual Basic)
In questo argomento viene illustrato come modificare una struttura ad albero dell'espressione. Le strutture ad albero dell'espressione sono immutabili, ovvero non possono essere modificate direttamente. Per modificare una struttura ad albero dell'espressione è necessario creare una copia di una struttura esistente e apportare le modifiche necessarie durante le creazione di tale copia. È possibile utilizzare la classe ExpressionVisitor per attraversare una struttura ad albero dell'espressione e copiare ogni nodo visitato.
Nota
Il codice sorgente per la classe ExpressionVisitor è disponibile nel sito Web CodePlex.
Per modificare una struttura ad albero dell'espressione
In Visual Studio creare un nuovo progetto Applicazione console.
Aggiungere la classe AndAlsoModifier al progetto.
Questa classe eredita la classe ExpressionVisitor ed è specializzata per modificare le espressioni che rappresentano operazioni AND condizionali. Queste operazioni vengono modificate da AND condizionale in OR condizionale. A questo scopo la classe esegue l'override del metodo VisitBinary del tipo di base, in quanto le espressioni AND condizionali sono rappresentate come espressioni binarie. Nel metodo VisitBinary, se l'espressione passata rappresenta un'operazione AND condizionale, il codice costruisce una nuova espressione che contiene l'operatore OR condizionale anziché l'operatore AND condizionale. Se l'espressione passata a VisitBinary non rappresentare un'operazione AND condizionale, il metodo rinvia all'implementazione della classe base. I metodi della classe base costruiscono nodi simili alle strutture ad albero dell'espressione a cui vengono passati, tuttavia le sottostrutture ad albero dei nodi vengono sostituite con le strutture ad albero dell'espressione prodotte in modo ricorsivo dal visitatore.
Aggiungere una direttiva using (o un'istruzione Imports in Visual Basic) al file per lo spazio dei nomi System.Linq.Expressions.
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
public class AndAlsoModifier : ExpressionVisitor { public Expression Modify(Expression expression) { return Visit(expression); } protected override Expression VisitBinary(BinaryExpression b) { if (b.NodeType == ExpressionType.AndAlso) { Expression left = this.Visit(b.Left); Expression right = this.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); } return base.VisitBinary(b); } }
Aggiungere codice al metodo Main nel file Program.cs (Module1.vb in Visual Basic) per creare una struttura ad albero dell'espressione e passarla al metodo che la modificherà.
Nel codice seguente viene creata un'espressione che contiene un'operazione AND condizionale. Viene quindi creata un'istanza della classe AndAlsoModifier e viene passata l'espressione al metodo Modify di questa classe. Per mostrare la modifica viene restituito l'output delle strutture ad albero dell'espressione originale e modificata.
Aggiungere una direttiva using (o un'istruzione Imports in Visual Basic) al file per lo spazio dei nomi System.Linq.Expressions.
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"))
Expression<Func<string, bool>> expr = name => name.Length > 10 && name.StartsWith("G"); Console.WriteLine(expr); AndAlsoModifier treeModifier = new AndAlsoModifier(); Expression modifiedExpr = treeModifier.Modify((Expression) expr); Console.WriteLine(modifiedExpr); /* This code produces the following output: name => ((name.Length > 10) && name.StartsWith("G")) name => ((name.Length > 10) || name.StartsWith("G")) */
Compilare l'applicazione ed eseguirla.
Vedere anche
Attività
Procedura: eseguire strutture ad albero dell'espressione (C# e Visual Basic)