C\#표현 식 트 리 Expression Trees 지식 정리

7923 단어 C#표현 식 트 리
목차
  • 안내
  • Lambda 표현 식 생 성 표현 식 트 리
  • API 생 성 표현 식 트 리
  • 표현 식 트 리 해석
  • 표현 식 트 리 의 영구적
  • 컴 파일 식 트 리
  • 표현 식 트 리 실행
  • 표현 식 트 리 수정
  • 디 버 깅
  • 간단 한 소개
    표현 식 트 리 는 트 리 데이터 구조 로 코드 를 표시 합 니 다.그 중에서 모든 노드 는 표현 식 입 니 다.예 를 들 어 방법 호출 과 x표현 식 트 리 의 코드 를 편집 하고 연산 할 수 있 습 니 다.이렇게 하면 실행 가능 한 코드 를 동적 으로 수정 하고 서로 다른 데이터베이스 에서 LINQ 조 회 를 실행 하 며 동적 조 회 를 만 들 수 있다.
    표현 식 트 리 는 동적 언어 가 실 행 될 때(DLR)동적 언어 와.NET Framework 간 의 상호 작용 성 을 제공 하 는 데 도 사용 할 수 있 습 니 다.
    1.Lambda 표현 식 생 성 표현 식 트 리
    lambda 표현 식 이Expression<TDelegate>형식의 변수 에 할당 되면 컴 파일 러 는 이 lambda 표현 식 을 나타 내 는 표현 식 트 리 를 만 들 기 위해 코드 를 발사 할 수 있 습 니 다. 
    C\#컴 파 일 러 는 표현 식 lambda(또는 한 줄 lambda)에서 만 표현 식 트 리 를 생 성 할 수 있 습 니 다.
    다음 코드 예제 에 서 는 키워드 Expression 을 사용 하여 lambda 표현 식 을 만 듭 니 다.
    
     Expression<Action<int>> actionExpression = n => Console.WriteLine(n);
     Expression<Func<int, bool>> funcExpression1 = (n) => n < 0;
     Expression<Func<int, int, bool>> funcExpression2 = (n, m) => n - m == 0;
    2.API 생 성 표현 식 트 리
    API 를 통 해 표현 식 트 리 를 만 들 려 면Expression클래스 를 사용 해 야 합 니 다.
    다음 코드 예제 에 서 는 API 를 통 해 lambda 표현 식 을 만 드 는 방법 을 보 여 줍 니 다:num=>num==0
    
    //   Expression        
     // lambda:num => num == 0
     ParameterExpression pExpression = Expression.Parameter(typeof(int)); //  :num
     ConstantExpression cExpression = Expression.Constant(0); //  :0
     BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.Equal, pExpression, cExpression); //   :num == 0
     Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(bExpression, pExpression); //lambda    :num => num == 0
    코드 는Expression류 의 정적 방법 으로 생 성 됩 니 다.
    3.해석 식 트 리
    다음 코드 예제 에 서 는 lambda 표현 식 num=>num==0 을 나타 내 는 표현 식 트 리 를 어떻게 분해 하 는 지 보 여 줍 니 다.
    
    Expression<Func<int, bool>> funcExpression = num => num == 0;
     //    
     ParameterExpression pExpression = funcExpression.Parameters[0]; //lambda      
     BinaryExpression body = (BinaryExpression)funcExpression.Body; //lambda      :num == 0
     Console.WriteLine($"  :{pExpression.Name} => {body.Left} {body.NodeType} {body.Right}");
    

    4.표현 식 트 리 영구적
    표현 식 트 리 는 영구적(문자열 과 유사)이 어야 합 니 다.이것 은 표현 식 트 리 를 수정 하려 면 이 표현 식 트 리 를 복사 한 다음 노드 를 바 꾸 어 새로운 표현 식 트 리 를 만들어 야 한 다 는 것 을 의미 합 니 다.  표현 식 트 리 를 사용 하여 방문 자 들 이 기 존 표현 식 트 리 를 옮 겨 다 닐 수 있 습 니 다.7 절 은 표현 식 트 리 를 어떻게 수정 하 는 지 소개 했다.
    5.컴 파일 식 트 리
    Expression<TDelegate>형식 은 표현 식 트 리 가 표시 하 는 코드 를 실행 가능 한 의뢰 로 컴 파일 하 는 방법 을 제공 합 니 다.
    
    //      
     Expression<Func<string, int>> funcExpression = msg => msg.Length;
     //         
     var lambda = funcExpression.Compile();
     //    
     Console.WriteLine(lambda("Hello, World!"));
     //    
     Console.WriteLine(funcExpression.Compile()("Hello, World!"));

    6.표현 식 트 리 실행
    표현 식 트 리 를 실행 하면 값 을 되 돌려 줄 수도 있 고,한 동작 만 수행 할 수도 있 습 니 다.(예 를 들 어 호출 방법)
    lambda 표현 식 을 표시 하 는 표현 식 트 리 만 실행 할 수 있 습 니 다.lambda 표현 식 을 나타 내 는 표현 식 트 리 는Compile또는LambdaExpression형식 에 속 합 니 다.이 표현 식 트 리 를 실행 하려 면 실행 가능 한 의뢰 를 만 들 고 이 의뢰 를 호출 하 는 방법Expression<TDelegate>을 사용 해 야 합 니 다.
    
    const int n = 1;
     const int m = 2;
     //        
     BinaryExpression bExpression = Expression.Add(Expression.Constant(n), Expression.Constant(m));
     //   lambda    
     Expression<Func<int>> funcExpression = Expression.Lambda<Func<int>>(bExpression);
     //   lambda    
     Func<int> func = funcExpression.Compile();
     //   lambda    
     Console.WriteLine($"{n} + {m} = {func()}");
    

    7.표현 식 트 리 수정
    이 클래스 계승Compile클래스,Visit 방법 을 통 해 VisitBinary 방법 을 간접 적 으로 호출 합 니 다!==로 바꾸다.기본 적 인 방법 은 들 어 오 는 표현 식 트 리 와 유사 한 노드 를 구성 하지만 이 노드 들 은 하위 디 렉 터 리 트 리 를 방문 기 재 귀적 으로 생 성 된 표현 식 트 리 로 대체 합 니 다. 
    
    internal class Program
     {
     private static void Main(string[] args)
     {
     Expression<Func<int, bool>> funcExpression = num => num == 0;
     Console.WriteLine($"Source: {funcExpression}");
     var visitor = new NotEqualExpressionVisitor();
     var expression = visitor.Visit(funcExpression);
     Console.WriteLine($"Modify: {expression}");
     Console.Read();
     }
     /// <summary>
     ///          
     /// </summary>
     public class NotEqualExpressionVisitor : ExpressionVisitor
     {
     public Expression Visit(BinaryExpression node)
     {
     return VisitBinary(node);
     }
     protected override Expression VisitBinary(BinaryExpression node)
     {
     return node.NodeType == ExpressionType.Equal
      ? Expression.MakeBinary(ExpressionType.NotEqual, node.Left, node.Right) //       :  !=    ==
      : base.VisitBinary(node);
     }
     }
     }
    

    8.디 버 깅
    8.1 매개 변수 표현 식
    
     ParameterExpression pExpression1 = Expression.Parameter(typeof(string));
     ParameterExpression pExpression2 = Expression.Parameter(typeof(string), "msg");

    그림 8-1

    그림 8-2
    DebugView 에서 알 수 있 듯 이 매개 변수 에 이름 이 없 으 면 자동 으로 생 성 된 이름 을 할당 합 니 다.
    
     const int num1 = 250;
     const float num2 = 250;
     ConstantExpression cExpression1 = Expression.Constant(num1);
     ConstantExpression cExpression2 = Expression.Constant(num2);

    그림 8-3

    그림 8-4
    DebugView 에서 알 수 있 듯 이 float 는 int 보다 접미사 F 가 많 습 니 다.
    
     Expression lambda1 = Expression.Lambda<Func<int>>(Expression.Constant(250));
     Expression lambda2 = Expression.Lambda<Func<int>>(Expression.Constant(250), "CustomName", null);

    그림 8-5

    그림 8-6
    DebugView 를 관찰 하면 lambda 표현 식 에 이름 이 없 으 면 자동 으로 생 성 된 이름 을 할당 합 니 다.
    이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.또한 저 희 를 많이 지지 해 주시 기 바 랍 니 다!

    좋은 웹페이지 즐겨찾기