表达式树练习实践:入门基础
什么是表達式樹
來自微軟官方文檔的定義:
表達式樹以樹形數(shù)據(jù)結構表示代碼。
它能干什么呢?
你可以對表達式樹中的代碼進行編輯和運算。這樣能夠動態(tài)修改可執(zhí)行代碼、在不同數(shù)據(jù)庫中執(zhí)行 LINQ 查詢以及創(chuàng)建動態(tài)查詢。
好不好玩?
表達式樹還能用于動態(tài)語言運行時 (DLR) 以提供動態(tài)語言和 .NET Framework 之間的互操作性,同時保證編譯器編寫員能夠發(fā)射表達式樹而非 Microsoft 中間語言 (MSIL)。
哪里有應用?
ORM框架、工作流框架等,使用到 Lambda 的代碼。。。動態(tài)執(zhí)行代碼、動態(tài)組裝代碼等。
創(chuàng)建表達式樹
創(chuàng)建表達式樹有兩種方式:通過 lambda 表達式、通過 API。
創(chuàng)建表達式樹的意思是,在此之前已經(jīng)編寫好每個結點,最后使用代碼將所有結點組合起來,生成表達式樹。
示例(通過API創(chuàng)建表達式樹)
```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();上面關于表達式樹的代碼很多,以下這一步叫生成/創(chuàng)建表達式樹。
Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);以下這句叫執(zhí)行表達式樹
var com = func.Compile();其它代碼是用于生成表達式樹結點/邏輯。
回歸正題,創(chuàng)建表達式樹的兩種方法。
lambda 創(chuàng)建表達式樹
上面的表達式樹示例,是用于生成
( 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 創(chuàng)建表達式樹
就是這樣
Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);兩種方式左邊的都是一樣的,區(qū)別在于等號右邊。
Expression< TDelegate >
上面示例的最終結果都是生成
Expression<Func<int, int, int, int, int>> funcfunc 是表達式樹變量。
我們可以了解以下表達式樹具有的方法和屬性。
用于生成表達式樹結點的,是 Expression 類型。
那么,創(chuàng)建的表達式樹 func ,是?Expression<TDelegate>類型。
定義如下
public sealed class Expression<TDelegate> : LambdaExpression具有方法如下
| Compile() | 將表達式樹描述的 lambda 表達式編譯為可執(zhí)行代碼,并生成表示 lambda 表達式的委托。 |
| Compile(Boolean) | 將表達式樹描述的 Lambda 表達式編譯為已解釋或已編譯的代碼,并生成表示該 Lambda 表達式的委托。 |
| Compile(DebugInfoGenerator) | 將 lambda 編譯到方法定義中。(Inherited from LambdaExpression) |
| Update(Expression, IEnumerable) | 創(chuàng)建一個與此表達式類似的新表達式,但使用所提供的子級。如果所有子級都相同,則將返回此表達式。 |
| Accept(ExpressionVisitor) | 調度到此節(jié)點類型的特定 Visit 方法。例如,MethodCallExpression調用 VisitMethodCall。 |
由于?Expression<TDelegate>?繼承了?LambdaExpression,所以有很多屬性方法也可以用。
| CanReduce | 指示可將節(jié)點簡化為更簡單的節(jié)點。如果返回 true,則可以調用 Reduce() 以生成簡化形式。 |
| Name | 獲取 lambda 表達式的名稱。 |
| NodeType | 返回此 Expression 的節(jié)點類型。 |
| Parameters | 獲取 lambda 表達式的參數(shù)。 |
| ReturnType | 獲取 lambda 表達式的返回類型。 |
| TailCall | 獲取一個值,該值指示是否將通過尾調用優(yōu)化來編譯 lambda 表達式。 |
| Type | 獲取此 Expression 表示的表達式的靜態(tài)類型。 |
好了,以上權當小筆記,備忘,目前先用不上,后面慢慢來使用。
解析/執(zhí)行表達式樹
創(chuàng)建表達式樹后,就要執(zhí)行表達式樹。
在此之前,你需要了解 委托 Delegate,Func,Action,以及他們中間的關系。
執(zhí)行表達式樹是這樣子的
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();四個參數(shù),一個返回值。
var runRasult = com(12, 12, 13, 13);C#里有語法糖,對委托可以這樣寫
以后后面都是這樣寫了,能夠縮成一行的代碼,就沒必要寫出兩行。
在 Vs 里面調試和查看表達式樹,可以看這里
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/expression-trees/debugging-expression-trees-in-visual-studio
初學者不必糾結于這些,了解一下本文內容,記一下概要信息即可。
總結
以上是生活随笔為你收集整理的表达式树练习实践:入门基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高性能最终一致性框架Ray之基本概念原理
- 下一篇: 尝鲜体验 VS Code Python