Gewusst wie: Ändern von Ausdrucksbaumstrukturen

Aktualisiert: November 2007

In diesem Thema wird beschrieben, wie eine Ausdrucksbaumstruktur geändert wird. Ausdrucksbaumstrukturen sind unveränderlich. Das bedeutet, dass sie nicht direkt geändert werden können. Um eine Ausdrucksbaumstruktur zu ändern, müssen Sie eine Kopie einer vorhandenen Ausdrucksbaumstruktur erstellen und beim Erstellen der Kopie die erforderlichen Änderungen vornehmen. Sie können einen Ausdrucksbaumstruktur-Besucher verwenden, um eine vorhandene Ausdrucksbaumstruktur zu durchlaufen und jeden aufgerufenen Knoten zu kopieren.

So ändern Sie eine Ausdrucksbaumstruktur

  1. Erstellen Sie in Visual Studio ein neues Konsolenanwendungsprojekt.

  2. Fügen Sie einen Verweis auf System.Core.dll hinzu, wenn er noch nicht existiert.

  3. Fügen Sie dem Projekt die ExpressionVisitor-Klasse hinzu.

    Dieser Code ist unter Gewusst wie: Implementieren eines Ausdrucksbaumstruktur-Besuchers verfügbar.

    Fügen Sie using-Direktiven (oder Imports-Anweisungen in Visual Basic) für die folgenden Namespaces hinzu: System.Collections.Generic, System.Collections.ObjectModel und System.Linq.Expressions.

  4. Fügen Sie dem Projekt die AndAlsoModifier-Klasse hinzu.

    Diese Klasse erbt die ExpressionVisitor-Klasse und wird spezialisiert, um Ausdrücke zu ändern, die bedingte AND-Operationen darstellen. Die Klasse ändert diese Operationen von einem bedingten AND in ein bedingtes OR. Dazu überschreibt die Klasse die VisitBinary-Methode des Basistyps, da bedingte AND-Ausdrücke als binäre Ausdrücke dargestellt werden. Für die VisitBinary-Methode gilt Folgendes: Wenn der Ausdruck, der an die Methode übergeben wird, eine bedingte AND-Operation darstellt, erstellt der Code einen neuen Ausdruck, der den bedingten OR-Operator anstelle des bedingten AND-Operators enthält. Wenn der Ausdruck, der an VisitBinary übergeben wird, keine bedingte AND-Operation darstellt, richtet sich die Methode nach der Basisklassenimplementierung. Die Basisklassenmethode erstellt Knoten, die den übergebenen Ausdrucksbaumstrukturen ähneln. In diesem Fall sind die Teilstrukturen der Knoten jedoch durch die Ausdrucksbaumstrukturen ersetzt, die vom Besucher rekursiv erstellt werden.

    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);
        }
    }
    

    Fügen Sie eine using-Direktive (oder Imports-Anweisung in Visual Basic) für den System.Linq.Expressions-Namespace der Datei hinzu.

  5. Fügen Sie der Main-Methode in der Datei Program.cs (Module1.vb in Visual Basic) Code hinzu, um eine Ausdrucksbaumstruktur zu erstellen und an die Methode zu übergeben, die sie ändert.

    Der folgende Code erstellt einen Ausdruck, der eine bedingte AND-Operation enthält. Anschließend wird eine Instanz der AndAlsoModifier-Klasse erstellt, und der Ausdruck wird an die Modify-Methode dieser Klasse übergeben. Sowohl die ursprüngliche als auch die geänderte Ausdrucksbaumstruktur werden ausgegeben, um die Änderung anzuzeigen.

    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"))
    */
    
    

    Fügen Sie eine using-Direktive (oder Imports-Anweisung in Visual Basic) für den System.Linq.Expressions-Namespace der Datei hinzu.

  6. Kompilieren Sie die Anwendung, und führen Sie sie aus.

Siehe auch

Aufgaben

Gewusst wie: Ausführen von Ausdrucksbaumstrukturen

Exemplarische Vorgehensweise: Erstellen eines IQueryable-LINQ-Anbieters

Gewusst wie: Implementieren eines Ausdrucksbaumstruktur-Besuchers

Konzepte

Ausdrucksbaumstrukturen