表達式樹練習實踐:入門基礎

来源:https://www.cnblogs.com/whuanle/archive/2019/09/21/11562372.html
-Advertisement-
Play Games

表達式樹練習實踐:入門基礎 [TOC] 什麼是表達式樹 來自微軟官方文檔的定義: 表達式樹以樹形數據結構表示代碼。 它能幹什麼呢? 你可以對錶達式樹中的代碼進行編輯和運算。 這樣能夠動態修改可執行代碼、在不同資料庫中執行 LINQ 查詢以及創建動態查詢。 好不好玩? 表達式樹還能用於動態語言運行時 ...


目錄

表達式樹練習實踐:入門基礎

img

什麼是表達式樹

來自微軟官方文檔的定義:

表達式樹以樹形數據結構表示代碼。

它能幹什麼呢?

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

好不好玩?

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

哪裡有應用?

ORM框架、工作流框架等,使用到 Lambda 的代碼。。。動態執行代碼、動態組裝代碼等。

創建表達式樹

創建表達式樹有兩種方式:通過 lambda 表達式、通過 API。

創建表達式樹的意思是,在此之前已經編寫好每個結點,最後使用代碼將所有結點組合起來,生成表達式樹。

示例(通過API創建表達式樹)

```
            ParameterExpression a = Expression.Parameter(typeof(int), "i");
            ParameterExpression b = Expression.Parameter(typeof(int), "j");

            Expression r1 = Expression.Multiply(a, b);      //乘法運行
            ParameterExpression c = Expression.Parameter(typeof(int), "x");
            ParameterExpression d = Expression.Parameter(typeof(int), "y");
            Expression r2 = Expression.Multiply(c, d);      //乘法運行

            Expression result = Expression.Add(r1, r2);     //相加
            //以上代碼產生結點
            //生成表達式
            Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);
            var com = func.Compile();
            Console.WriteLine("表達式" + func);
            Console.WriteLine(com(12, 12, 13, 13));
            Console.ReadKey();

上面關於表達式樹的代碼很多,以下這一步叫生成/創建表達式樹。

            Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);

以下這句叫執行表達式樹

            var com = func.Compile();

其它代碼是用於生成表達式樹結點/邏輯。

回歸正題,創建表達式樹的兩種方法。

lambda 創建表達式樹

上面的表達式樹示例,是用於生成

 ( i * j ) + ( x * y ) 

但是就這麼簡單的操作,要寫這麼長,實在不合理。

而通過 lambda ,可以這樣寫

           Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (i * j) + (x * y);

如果使用 lambda 生成表達式樹, lambda 只能使用單行語句,不能使用 if、for等語句。

具體關於 Lambda 的表達式樹,後面其它文章有說明。

通過 API 創建表達式樹

就是這樣

Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);

兩種方式左邊的都是一樣的,區別在於等號右邊。

Expression< TDelegate >

上面示例的最終結果都是生成

Expression<Func<int, int, int, int, int>> func 

func 是表達式樹變數。

我們可以瞭解以下表達式樹具有的方法和屬性。

用於生成表達式樹結點的,是 Expression 類型。

那麼,創建的表達式樹 func ,是 Expression<TDelegate>類型。

定義如下

public sealed class Expression<TDelegate> : LambdaExpression

具有方法如下

定義

方法 說明
Compile() 將表達式樹描述的 lambda 表達式編譯為可執行代碼,並生成表示 lambda 表達式的委托。
Compile(Boolean) 將表達式樹描述的 Lambda 表達式編譯為已解釋或已編譯的代碼,並生成表示該 Lambda 表達式的委托。
Compile(DebugInfoGenerator) 將 lambda 編譯到方法定義中。 (Inherited from LambdaExpression)
Update(Expression, IEnumerable) 創建一個與此表達式類似的新表達式,但使用所提供的子級。 如果所有子級都相同,則將返回此表達式。
Accept(ExpressionVisitor) 調度到此節點類型的特定 Visit 方法。 例如,MethodCallExpression調用 VisitMethodCall。

由於 Expression<TDelegate> 繼承了 LambdaExpression,所以有很多屬性方法也可以用。

LambdaExpression

Body 獲取 lambda 表達式的主體。
CanReduce 指示可將節點簡化為更簡單的節點。 如果返回 true,則可以調用 Reduce() 以生成簡化形式。
Name 獲取 lambda 表達式的名稱。
NodeType 返回此 Expression 的節點類型。
Parameters 獲取 lambda 表達式的參數。
ReturnType 獲取 lambda 表達式的返回類型。
TailCall 獲取一個值,該值指示是否將通過尾調用優化來編譯 lambda 表達式。
Type 獲取此 Expression 表示的表達式的靜態類型。

好了,以上權當小筆記,備忘,目前先用不上,後面慢慢來使用。

解析/執行表達式樹

創建表達式樹後,就要執行表達式樹。

在此之前,你需要瞭解 委托 Delegate,Func,Action,以及他們中間的關係。

執行表達式樹是這樣子的

            Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);
            var com = func.Compile();
            var runRasult = com(12, 12, 13, 13);

func 只是一個表達式樹,我們把表達式樹構建好後,“要將表達式樹轉為代碼”,使用

.Compile() 方法,可以將表達式樹生成一個 委托(例如上面的 com)。

為了簡潔上面使用了 var,實際上是這樣的

            Func<int,int,int,int,int> com = func.Compile();

四個參數,一個返回值。

var runRasult = com(12, 12, 13, 13);

C#里有語法糖,對委托可以這樣寫

        Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);

        int runRasult = func.Compile()(12, 12, 13, 13);

以後後面都是這樣寫了,能夠縮成一行的代碼,就沒必要寫出兩行。

在 Vs 裡面調試和查看表達式樹,可以看這裡

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/expression-trees/debugging-expression-trees-in-visual-studio

初學者不必糾結於這些,瞭解一下本文內容,記一下概要信息即可。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Excel文件讀、寫可以使用Office自帶的庫(Microsoft.Office.Interop.Excel),前提是本機須安裝office才能運行,且不同的office版本之間可能會有相容問題。還可以使用NPOI,在不安裝office的時候也是可以讀寫的,速度很快。當然,還有支持Excel200 ...
  • 第一次接觸到Cache的時候,是在WebForm中,第一次接觸,我就再也沒能忘記,cache(擦車,的拼音) 客戶端瀏覽器緩存https://blog.csdn.net/y874961524/article/details/61419716 CDN緩存原理https://www.cnblogs.co ...
  • 因為有時候需要定製化的控制項,需要多個控制項的組合及複雜功能的集成,這樣可以考慮自定義用戶控制項。下麵分享一個簡單的數值增減功能的自定義控制項作為說明。 效果圖如下: 1、創建自定義用戶控制項(添加->新建項->用戶控制項) 2、編寫XAML UI比較簡單,我就不解釋了... 2、編寫後臺代碼 邏輯也比較簡單, ...
  • WPF依賴項屬性可以實現屬性的綁定,成功綁定之後只要修改後臺綁定的屬性,即可UI同步自動更新綁定的值,無需手動刷新界面;同樣,前臺的值變化後,通過獲取綁定的屬性值也可獲取UI變化後的值,實現雙向變化的效果。屬性綁定使得UI更新非常的方便,下麵分享一個小慄子說明使用的方式。 1、先做了一個有一個Tex ...
  • JIT--第一次--標記已--存根--調用--查找存根--執行機器碼 C#和CIL的關係: C#和N#都是CIL實現,但是彼此不能互通: C#和N#公開不分滿足規範,我們才能互通 CLS就是描述多語言互通的規範 記憶體分配:線程棧 堆Heap: 一個程式運行時,該進程存放引用類型變數的一塊記憶體,全局唯 ...
  • 參考地址:https://blog.csdn.net/qiaoquan3/article/details/51380992 1、集合set:純粹的數據集合 2、線性結構:一對一的,數組 3、樹形結構:一對多的,菜單/文件夾/類別/屬性控制項/表達式目錄樹 4、圖形/網狀結構:多對多,地圖應用比較多,網 ...
  • 需求場景 網站a,功能變數名稱為 a.site.com 網站b, 功能變數名稱為 b.site.com 需要在a、b兩個站點之間共用session 解決方案 使用redis作為分散式緩存存儲 設置sessionId cookie 保存的功能變數名稱,使得兩個網站鈞能夠讀取到相同的sessionId 自定義SessionMi ...
  • https://www.cnblogs.com/chenwolong/p/7531955.html EF使用AsNoTracking(),無跟蹤查詢技術(查詢出來的數據不可以修改,如果你做了修改,你會發現修改並不成功) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...