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

来源: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
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...