国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C# 表達式樹Expression Trees的知識梳理

2019-10-29 21:16:08
字體:
來源:轉載
供稿:網友

目錄

  • 簡介
  • Lambda 表達式創建表達式樹
  • API 創建表達式樹
  • 解析表達式樹
  • 表達式樹的永久性
  • 編譯表達式樹
  • 執行表達式樹
  • 修改表達式樹
  • 調試

簡介

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

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

表達式樹還能用于動態語言運行時 (DLR) 以提供動態語言和 .NET Framework 之間的互操作性。

一、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;

二、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 類的靜態方法進行創建。

三、解析表達式樹

下列代碼示例展示如何分解表示 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}");

C#,表達式樹

四、表達式樹永久性

表達式樹應具有永久性(類似字符串)。這意味著如果你想修改某個表達式樹,則必須復制該表達式樹然后替換其中的節點來創建一個新的表達式樹。  你可以使用表達式樹訪問者遍歷現有表達式樹。第七節介紹了如何修改表達式樹。

五、編譯表達式樹

Expression<TDelegate> 類型提供了 Compile 方法以將表達式樹表示的代碼編譯成可執行委托。

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

C#,表達式樹

六、執行表達式樹

執行表達式樹可能會返回一個值,也可能僅執行一個操作(例如調用方法)。

只能執行表示 lambda 表達式的表達式樹。表示 lambda 表達式的表達式樹屬于 LambdaExpressionExpression<TDelegate> 類型。若要執行這些表達式樹,需要調用 Compile 方法來創建一個可執行委托,然后調用該委托。

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

C#,表達式樹

七、修改表達式樹

該類繼承 ExpressionVisitor 類,通過 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); } } }

C#,表達式樹

八、調試

8.1 參數表達式

 ParameterExpression pExpression1 = Expression.Parameter(typeof(string)); ParameterExpression pExpression2 = Expression.Parameter(typeof(string), "msg");

C#,表達式樹

圖8-1

C#,表達式樹

圖8-2

從 DebugView 可知,如果參數沒有名稱,則會為其分配一個自動生成的名稱。

 const int num1 = 250; const float num2 = 250; ConstantExpression cExpression1 = Expression.Constant(num1); ConstantExpression cExpression2 = Expression.Constant(num2);

C#,表達式樹

圖8-3

C#,表達式樹

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

C#,表達式樹

圖8-5

C#,表達式樹

圖8-6

觀察 DebugView ,如果 lambda 表達式沒有名稱,則會為其分配一個自動生成的名稱。

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持VEVB武林網!


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 蒲江县| 阳江市| 大兴区| 通海县| 修文县| 通州市| 句容市| 潞西市| 鹤山市| 阿合奇县| 威海市| 武功县| 时尚| 闸北区| 抚远县| 浏阳市| 上高县| 安图县| 达拉特旗| 宜兰市| 万载县| 观塘区| 濮阳市| 达日县| 绥棱县| 调兵山市| 奉节县| 皋兰县| 平谷区| 华蓥市| 绵竹市| 灌阳县| 田东县| 浮山县| 顺义区| 枝江市| 汉中市| 永吉县| 林西县| 建德市| 嘉祥县|