다음을 통해 공유


방법: 식 트리 수정

업데이트: 2007년 11월

이 항목에서는 식 트리를 수정하는 방법을 보여 줍니다. 식 트리는 변경 불가능하므로 직접 수정할 수 없습니다. 식 트리를 변경하려면 기존 식 트리의 복사본을 만들어야 하고, 복사본을 만들 때 필요한 변경 작업을 수행해야 합니다. 식 트리 방문자를 사용하여 기존 식 트리를 이동하고 방문한 각 노드를 복사할 수 있습니다.

식 트리를 수정하려면

  1. Visual Studio에서 콘솔 응용 프로그램 프로젝트를 새로 만듭니다.

  2. 아직 참조되지 않은 경우 System.Core.dll에 대한 참조를 추가합니다.

  3. ExpressionVisitor 클래스를 프로젝트에 추가합니다.

    이 코드는 방법: 식 트리 방문자 구현에서 사용할 수 있습니다.

    System.Collections.Generic, System.Collections.ObjectModel 및 System.Linq.Expressions 네임스페이스에 대한 using 지시문(Visual Basic의 경우 Imports 문)을 파일에 추가합니다.

  4. AndAlsoModifier 클래스를 프로젝트에 추가합니다.

    이 클래스는 ExpressionVisitor 클래스를 상속하며 조건부 AND 작업을 나타내는 식을 수정하는 데 사용됩니다. 이러한 작업을 조건부 AND에서 조건부 OR로 변경합니다. 조건부 AND 식은 이진 식으로 표시되므로 이 작업을 위해 클래스는 기본 형식의 VisitBinary 메서드를 재정의합니다. VisitBinary 메서드에서 전달된 식이 조건부 AND 연산을 나타내는 경우 코드에서 조건부 AND 연산자 대신 조건부 OR 연산자를 포함하는 새 식이 생성됩니다. VisitBinary로 전달된 식이 조건부 AND 연산을 나타내지 않으면 메서드에서 기본 클래스 구현을 따릅니다. 기본 클래스 메서드는 전달된 식 트리와 같은 노드를 생성하지만 노드의 하위 트리가 방문자에 의해 재귀적으로 생성된 식 트리로 바뀝니다.

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

    System.Linq.Expressions 네임스페이스에 대한 using 지시문(Visual Basic의 경우 Imports 문)을 파일에 추가합니다.

  5. Program.cs(Visual Basic의 경우 Module1.vb) 파일의 Main 메서드에 코드를 추가하여 식 트리를 만들고 해당 식 트리를 수정할 메서드로 전달합니다.

    다음 코드에서는 조건부 AND 연산이 포함된 식을 만듭니다. AndAlsoModifier 클래스의 인스턴스를 만들고 이 클래스의 Modify 메서드에 식을 전달합니다. 원래 식 트리와 수정된 식 트리가 모두 출력되어 변경 내용을 표시합니다.

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

    System.Linq.Expressions 네임스페이스에 대한 using 지시문(Visual Basic의 경우 Imports 문)을 파일에 추가합니다.

  6. 응용 프로그램을 컴파일하여 실행합니다.

참고 항목

작업

방법: 식 트리 실행

연습: IQueryable LINQ 공급자 만들기

방법: 식 트리 방문자 구현

개념

식 트리