程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> [C#] 說說表達式樹,

[C#] 說說表達式樹,

編輯:C#入門知識

[C#] 說說表達式樹,


說說表達式樹 - Expression Trees

  簡單說下表達式樹。

 

目錄

 

介紹

  表達式樹以樹形數據結構表示代碼,其中每一個節點都是一種表達式,比如方法調用和 x < y 這樣的二元運算等。

  你可以對表達式樹中的代碼進行編輯和運算。這樣能夠動態修改可執行代碼、在不同數據庫中執行 LINQ 查詢以及創建動態查詢。 

  表達式樹還能用於動態語言運行時 (DLR) 以提供動態語言和 .NET Framework 之間的互操作性,同時保證編譯器編寫員能夠發射表達式樹而非 Microsoft 中間語言 (MSIL)。 

 

一、根據 Lambda 表達式創建表達式樹

  若 lambda 表達式被分配給 Expression<TDelegate> 類型的變量,則編譯器可以發射代碼以創建表示該 lambda 表達式的表達式樹。  

  C# 編譯器只能從表達式 lambda (或單行 lambda)生成表達式樹。 

  下列代碼示例使用關鍵字 Expression創建表示 lambda 表達式:

1             Expression<Action<int>> actionExpression = n => Console.WriteLine(n);
2             Expression<Func<int, bool>> funcExpression1 = (n) => n < 0;
3             Expression<Func<int, int, bool>> funcExpression2 = (n, m) => n - m == 0;

 

二、通過 API 創建表達式樹

  通過 API 創建表達式樹需要使用 Expression 類

  下列代碼示例展示如何通過 API 創建表示 lambda 表達式:num => num == 0

1             //通過 Expression 類創建表達式樹
2             //  lambda:num => num == 0
3             ParameterExpression pExpression = Expression.Parameter(typeof(int));    //參數:num
4             ConstantExpression cExpression = Expression.Constant(0);    //常量:0
5             BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.Equal, pExpression, cExpression);   //二元表達式:num == 0
6             Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(bExpression, pExpression);  //lambda 表達式:num => num == 0

  代碼使用 Expression 類的靜態方法進行創建。

 

 三、解析表達式樹 

   下列代碼示例展示如何分解表示 lambda 表達式 num => num == 0 的表達式樹。

1             Expression<Func<int, bool>> funcExpression = num => num == 0;
2 
3             //開始解析
4             ParameterExpression pExpression = funcExpression.Parameters[0]; //lambda 表達式參數
5             BinaryExpression body = (BinaryExpression)funcExpression.Body;  //lambda 表達式主體:num == 0
6 
7             Console.WriteLine($"解析:{pExpression.Name} => {body.Left} {body.NodeType} {body.Right}");

1 //創建表達式樹 2 Expression<Func<string, int>> funcExpression = msg => msg.Length; 3 //表達式樹編譯成委托 4 var lambda = funcExpression.Compile(); 5 //調用委托 6 Console.WriteLine(lambda("Hello, World!")); 7 8 //語法簡化 9 Console.WriteLine(funcExpression.Compile()("Hello, World!"));

1 const int n = 1; 2 const int m = 2; 3 4 //待執行的表達式樹 5 BinaryExpression bExpression = Expression.Add(Expression.Constant(n), Expression.Constant(m)); 6 //創建 lambda 表達式 7 Expression<Func<int>> funcExpression = Expression.Lambda<Func<int>>(bExpression); 8 //編譯 lambda 表達式 9 Func<int> func = funcExpression.Compile(); 10 11 //執行 lambda 表達式 12 Console.WriteLine($"{n} + {m} = {func()}");

 

七、如何:修改表達式樹 

   該類繼承 ExpressionVisitor 類,並且專用於修改表示條件 AND 運算的表達式。它將這些運算從條件 AND 更改為條件 OR。為此,該類將重寫基類型的 VisitBinary 方法,這是因為條件 AND 表達式表示為二元表達式。在 VisitBinary 方法中,如果傳遞到該方法的表達式表示條件AND 運算,代碼將構造一個包含條件 OR 運算符(而不是條件 AND 運算符)的新表達式。如果傳遞到 VisitBinary 的表達式不表示條件 AND運算,則該方法交由基類實現來處理。  基類方法構造類似於傳入的表達式樹的節點,但這些節點將其子目錄樹替換為訪問器遞歸生成的表達式樹。  

 1     internal class Program
 2     {
 3         private static void Main(string[] args)
 4         {
 5             Expression<Func<int, bool>> funcExpression = num => num == 0;
 6             Console.WriteLine($"Source: {funcExpression}");
 7 
 8             var visitor = new NotEqualExpressionVisitor();
 9             var expression = visitor.Visit(funcExpression);
10 
11             Console.WriteLine($"Modify: {expression}");
12 
13             Console.Read();
14         }
15 
16         /// <summary>
17         /// 不等表達式樹訪問器
18         /// </summary>
19         public class NotEqualExpressionVisitor : ExpressionVisitor
20         {
21             public Expression Visit(BinaryExpression node)
22             {
23                 return VisitBinary(node);
24             }
25 
26             protected override Expression VisitBinary(BinaryExpression node)
27             {
28                 return node.NodeType == ExpressionType.Equal
29                     ? Expression.MakeBinary(ExpressionType.NotEqual, node.Left, node.Right) //重新弄個表達式:用 != 代替 ==
30                     : base.VisitBinary(node);
31             }
32         }
33     }

 

 


【原文鏈接】http://www.cnblogs.com/liqingwen/p/5868688.html 

 

預覽版,更新於09/16

 

  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved