방법: 식 트리 수정(C# 및 Visual Basic)

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

참고

CodePlex 웹 사이트에서 ExpressionVisitor 클래스의 소스 코드를 볼 수 있습니다.

식 트리를 수정하려면

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

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

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

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

    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);
        }
    }
    
  3. Program.cs(Visual Basic의 경우 Module1.vb) 파일의 Main 메서드에 코드를 추가하여 식 트리를 만들고 해당 식 트리를 수정할 메서드로 전달합니다.

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

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

            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"))
                */
    
    
  4. 응용 프로그램을 컴파일하여 실행합니다.

참고 항목

작업

방법: 식 트리 실행(C# 및 Visual Basic)

개념

식 트리(C# 및 Visual Basic)