日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

共享一个从字符串转 Lambda 表达式的类(4)

發(fā)布時間:2025/4/14 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 共享一个从字符串转 Lambda 表达式的类(4) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

開始寫第四篇,別的不說了。這篇將涉及到如何使用字符串解析結(jié)果,生成一個 Lambda 表達(dá)式樹。東西有點多,我先整理一下思路,在下面說明一下。如果你有問題,在后面的評論上寫下來,我看到了會回復(fù)你。

?

?

在前幾篇中,我寫了一個字符串解析模塊,還有一個根據(jù)字符串解析成 Type 對象的類型分析模塊。這兩個模塊,都將為這個 Expression 核心解析類提供輔助,所以如果前兩篇文章你沒有看到,可以到我博客中先把前幾篇文章看一下,理解我的整體思路后,再回過頭來看這篇。

?

我希望從這篇文章開始,看到一些有用的評論,謝謝了!

?

?

Expression 核心解析類(ExpressionParserCore)對外發(fā)布的只有一個方法 —— ToLambdaExpression ,用于輸出分析得到的 Lambda 表達(dá)式樹。在貼代碼之前,我把大致思路說明一下:

?

?

首先,需要幾個前提條件:

1.? 待分析的字符串

2.? Lambda 表達(dá)式樹包含的委托類型

3.? 類型解析可能用到的命名空間和程序集列表

?

第一個,很好理解,在這里不做闡述。

第二個,是告訴要解析的目標(biāo)參數(shù)和返回值信息。

第三個,類型解析中會用到,這里只是做一下參數(shù)傳遞。具體的代碼可以參看第三篇。

?

?

其次,由于 Lambda 表達(dá)式樹的遞歸特性,所以其解析工作不可能一蹴而就,所以解析工作將其拆分為三步:

1.? ReadFirstExpression

2.? ReadNextExpression

3.? ReadExpression

?

從字面上可以看出來:ReadFirstExpression 是讀取第一個 Expression ,ReadNextExpression 是讀取接下來的 Expression ,ReadExpression 是讀取 Expression 。

?

?

ReadFirstExpression:讀取第一個 Expression ,不去管后面是不是還有沒有解析的 Expression 。比如:【() => 1 + 2】這個表達(dá)式,如果使用該方法則只會讀取常量表達(dá)式【1】,不會繼續(xù)讀取剩下的常量表達(dá)式【2】和加法表達(dá)式。一句話總結(jié):讀取了一個 Expression 就停止讀取。

?

?

ReadNextExpression:讀取下一個 Expression ,在已讀取了表達(dá)式的基礎(chǔ)上繼續(xù)解析 Expression 。接著上面的表達(dá)式【() => 1 + 2】繼續(xù)說,讀取了表達(dá)式【1】后,繼續(xù)讀取常量表達(dá)式【2】,再繼續(xù)讀取加法表達(dá)式,返回整個表達(dá)式。

?

到了這里,有人會問:為什么會分成讀取第一個和讀取下一個兩個方法?有以下原因吧,我感覺分開好些:

1.? 有些表達(dá)式不能作為第一個表達(dá)式(比如加法表達(dá)式),有些不能作為后續(xù)的表達(dá)式(比如求反表達(dá)式)。

2.? 就是有些符號不能在開始表達(dá)式中(比如右括號),有些不能作為在結(jié)束表達(dá)式中(比如左括號)。

3.? 開始表達(dá)式從零構(gòu)造一個表達(dá)式,后續(xù)表達(dá)式需要一個前置表達(dá)式。

還有一些,暫時想到的就這些了。

?

?

ReadExpression:讀取表達(dá)式,可以遞歸調(diào)用實現(xiàn) Expression 的遞歸。在發(fā)布的方法 ToLambdaExpression 中,調(diào)用的就是 ReadExpression ,進(jìn)行第一次的遞歸操作。在表達(dá)式中如果需要,可能會多次調(diào)用,比如表達(dá)式【() => 1 + 2】會調(diào)用兩次:一次是開始調(diào)用 ToLambdaExpression 的時候,一次是解析常量表達(dá)式【2】的時候。

?

在此,我把大概的流程用【() => 1 + 2】說明一下吧:

1.? 準(zhǔn)備前提條件。

2.? 將字符串【() => 1 + 2】解析為我們需要的 Token 單元集合。

3.? 分析目標(biāo)委托類型(可以理解為 typeof(Func<int>).GetType() )為 0 個參數(shù),返回值為 int 的委托。

4.? 調(diào)用 ToLambdaExpression 開始解析 Lambda 表達(dá)式樹:第一次調(diào)用 ReadExpression 方法。

5.? ReadExpression 方法調(diào)用 ReadFirstExpression 方法獲取一個常量表達(dá)式樹【1】。

6.? ReadExpression 方法繼續(xù)調(diào)用 ReadNextExpression 方法,并傳遞參數(shù)常量表達(dá)式樹【1】。

7.? 讀取到加法表達(dá)式樹,將常量表達(dá)式樹【1】作為加法左邊的表達(dá)式樹,尚需要的右邊表達(dá)式樹,調(diào)用 ReadExpression 方法讀取。

8.? ReadExpression 方法調(diào)用 ReadFirstExpression 方法獲取一個常量表達(dá)式樹【2】。

9.? ReadExpression 方法繼續(xù)調(diào)用 ReadNextExpression 方法,并傳遞參數(shù)常量表達(dá)式樹【2】。

10. 發(fā)現(xiàn)已經(jīng)讀取到末尾,ReadNextExpression 方法返回傳遞進(jìn)來的參數(shù)常量表達(dá)式樹【2】。

11. ReadExpression 返回讀取到的常量表達(dá)式【2】,這里將返回到第 7 步。

12. 加法表達(dá)式的左右表達(dá)式均已具備,構(gòu)造加法表達(dá)式【1 + 2】,并返回到第 6 步。

13. 繼續(xù)讀取發(fā)現(xiàn)讀取到末尾,返回加法表達(dá)式【1 + 2】到第 4 步。

14. 根據(jù)委托類型構(gòu)造 Lambda 表達(dá)式樹并返回,解析完成。

?

我先將這三個方法的原型說明一下:

1.? ReadFirstExpression()

2.? ReadNextExpression(int level, ReadResult previousResult, TokenId? wrapStart = null)

3.? ReadExpression(int level = 0)

?

level???????? : 這個參數(shù)是運算符優(yōu)先級,優(yōu)先級越大該數(shù)字越大,比如【1 + 2 * 3】這個表達(dá)式,會先進(jìn)行【2 * 3】的組合而不是【1 + 2】的組合。

previousResult: 表示前面分析得到的結(jié)果。包含兩個屬性:表達(dá)式和是否讀取結(jié)束。

wrapStart???? : 表示讀取下一個表達(dá)式的前導(dǎo) Token 類型。previousResult 中的屬性【是否讀取結(jié)束】和這個參數(shù)相關(guān):每種括號的開始和結(jié)束對應(yīng)。

?

?

就到這里吧,寫太長了,估計多數(shù)人沒看下去的興趣。下篇我會把 ReadFirstExpression 方法的邏輯整理一下,順便貼出來部分代碼。如果你感覺我寫的東西有用,或者你期待下一篇,請點一下推薦,謝謝了!

轉(zhuǎn)載于:https://www.cnblogs.com/lenic/archive/2012/06/26/2563559.html

總結(jié)

以上是生活随笔為你收集整理的共享一个从字符串转 Lambda 表达式的类(4)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。