前排提醒:閱讀此文章並充分嘗試 ModVB 的新語法需要較長的時間。對於程式設計師而言,如果你工作時不用 VB,則最好避免在上班時間看,以免被領導認為你在長時間摸魚。
ModVB 是一個免費和獨立的 VB.NET 「mod」,裝一個 VSIX 和對應的 NuGet 包就能用新功能。
其中 mod 的意思包含:修改版(modified),現代(modern),以及 取模運算(modulo) (VB + ModVB) Mod VB = ModVB
。
Anthony D. Green 在微軟的託管程式語言團隊有八年工作經驗。大多時候是 Roslyn 編譯器團隊的專案群 / 專案集經理(Program Manager)。他從 13 歲起從 VB4 開始程式設計,在釋出 ModVB 的第一個公測版本時 37 歲。
注:編寫此文章時,Visual Studio 2022 版本為 17.3.2,外掛版本為 0.0.1.0。範例中使用的作業系統是 Windows 10 x64 專業版 21H2,簡體中文。
此步驟用於隔離裝了 ModVB 的環境和沒裝的環境,以便外掛的分別管理。
devenv /rootSuffix ModVB
"C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.exe" /rootSuffix ModVB
從選單上開啟 工具→選項,左側找到 環境→擴充套件
新增其他擴充套件庫:
https://www.myget.org/F/modvb/vsix/
點選應用(Apply)
還是在選項對話方塊裡。左側找到NuGet包管理器→程式包源
在右邊新增新的包源並且確保它已經打勾
https://www.myget.org/F/modvb/api/v3/index.json
點更新,然後確定。
注:由於程式碼高亮不完全支援這種修改過的 VB,對於未提及執行結果的程式碼,使用截圖表示。僅對於程式碼高亮沒問題的程式碼和帶有執行結果的程式碼使用文字表示。
如果下載速度慢,請自備對MyGet有效的加速器,或者找已經下載了並且你相信的人分享。
使用 JSON 相關語法之前首先需要選擇 JSON 常數使用哪些庫。目前可選的有 Newtonsoft.Json 和 System.Text.Json。
如果選擇 Newtonsoft.Json,則需要安裝
如果選擇 System.Text.Json,則需要安裝
預設情況下,JSON 常數和模式匹配使用 Newtonsoft.Json 定義的型別。如果選擇它之外的庫,則需要定義編譯常數來更改預設型別。
假設有個專案,上述兩種庫都安裝了。預設情況下,Json 物件是 Newtonsoft.Json.Linq.JObject。
如果想要預設用 System.Text.Json,需要在專案檔案中定義編譯常數。
<PropertyGroup>
<DefineConstants>DEFAULT_JSON_OBJECT_TYPE = "System.Text.Json.Nodes.JsonObject",DEFAULT_JSON_ARRAY_TYPE = "System.Text.Json.Nodes.JsonArray"</DefineConstants>
</PropertyGroup>
效果如下圖所示
那麼,如果一個專案裡想同時使用兩種JSON型別呢?也是能做到的。只不過你需要寫上JSON變數的型別,而不是讓編譯器自動推斷型別。
就像變數可以用 XML 常數初始化一樣,ModVB 支援用 JSON 常數初始化變數,並且用法與 XML 常數有一定的相似性。
此章節的範例使用 Newtonsoft.Json 作為預設 JSON 型別。
以 NuGet 工具版本查詢結果的片段為例。請求 https://dist.nuget.org/tools.json
能夠得到類似於這樣的 JSON並儲存在變數中:
假如你打算生成類似的 JSON,可以把別的變數直接寫進去換掉JSON的值。
有更多的版本需要顯示也是沒問題的,可以用 LINQ 表示式做個 JSON 物件陣列出來,然後放到總的 JSON 裡面。具體做法可參照下面的範例。
下列程式碼展示如何用 LINQ 結合 JSON 常數語法拼一個新的 JSON 出來。
ModVB
Module Program
Sub Main()
Dim latestVersion = "6.3.0"
Dim stableVersions = {
(ver:="6.2.1", uploaded:="2022-06-14T17:00:00.0000000Z"),
(ver:="6.2.0", uploaded:="2022-05-10T13:00:00.0000000Z"),
(ver:="6.1.0", uploaded:="2022-02-15T13:00:00.0000000Z")
}
Dim nugetVersions = {
"nuget.exe": [
{
"version": latestVersion,
"url": $"https://dist.nuget.org/win-x86-commandline/v{latestVersion}/nuget.exe",
"stage": "Released",
"uploaded": "2022-08-09T13:00:00.0000000Z"
},
From verInfo In stableVersions
Select {
"version": verInfo.ver,
"url": $"https://dist.nuget.org/win-x86-commandline/v{verInfo.ver}/nuget.exe",
"stage": "ReleasedAndBlessed",
"uploaded": verInfo.uploaded
}
]
}
Console.WriteLine(nugetVersions)
End Sub
End Module
這段程式碼的執行結果是:
JSON
{
"nuget.exe": [
{
"version": "6.3.0",
"url": "https://dist.nuget.org/win-x86-commandline/v6.3.0/nuget.exe",
"stage": "Released",
"uploaded": "2022-08-09T13:00:00.0000000Z"
},
{
"version": "6.2.1",
"url": "https://dist.nuget.org/win-x86-commandline/v6.2.1/nuget.exe",
"stage": "ReleasedAndBlessed",
"uploaded": "2022-06-14T17:00:00.0000000Z"
},
{
"version": "6.2.0",
"url": "https://dist.nuget.org/win-x86-commandline/v6.2.0/nuget.exe",
"stage": "ReleasedAndBlessed",
"uploaded": "2022-05-10T13:00:00.0000000Z"
},
{
"version": "6.1.0",
"url": "https://dist.nuget.org/win-x86-commandline/v6.1.0/nuget.exe",
"stage": "ReleasedAndBlessed",
"uploaded": "2022-02-15T13:00:00.0000000Z"
}
]
}
上面的例子如果你覺得 nugetVersions
的變數宣告太長了,你可以提取變數出來。JSON 常數支援扁平化操作,能夠用來將多個 JSON 物件合併成一個,而不導致物件層次加深。
下面的程式碼將第一個版本資訊中的兩個屬性提取了變數出來,並且剩餘版本資訊提取出了另一個變數。程式的執行結果不變。
ModVB
Module Program
Sub Main()
Dim latestVersion = "6.3.0"
Dim stableVersions = {
(ver:="6.2.1", uploaded:="2022-06-14T17:00:00.0000000Z"),
(ver:="6.2.0", uploaded:="2022-05-10T13:00:00.0000000Z"),
(ver:="6.1.0", uploaded:="2022-02-15T13:00:00.0000000Z")
}
Dim stable = From verInfo In stableVersions
Select {
"version": verInfo.ver,
"url": $"https://dist.nuget.org/win-x86-commandline/v{verInfo.ver}/nuget.exe",
"stage": "ReleasedAndBlessed",
"uploaded": verInfo.uploaded
}
Dim releasedStage = {
"stage": "Released",
"uploaded": "2022-08-09T13:00:00.0000000Z"
}
Dim nugetVersions = {
"nuget.exe": [
{
"version": latestVersion,
"url": $"https://dist.nuget.org/win-x86-commandline/v{latestVersion}/nuget.exe",
{releasedStage}
},
stable
]
}
Console.WriteLine(nugetVersions)
End Sub
End Module
JSON模式匹配能在判斷JSON的結構和內容的同時將所需的資訊提取成變數。
以 JSON 常數例子中的 JSON 為例。假設你需要取得所有 stage
是 ReleasedAndBlessed
的 nuget.exe
版本以及其它資訊,可以用下面的程式碼:
ModVB
Console.WriteLine("所有已釋出的穩定版:")
Select Case ShapeOf nugetVersions
Case {"nuget.exe": nodes}
For Each node In nodes
Select Case ShapeOf node
Case {
"version": ver As Version,
"url": url As String,
"stage": "ReleasedAndBlessed",
"uploaded": relaseDate As Date
}
Console.WriteLine($"{ver} 釋出於 {relaseDate:F},下載地址是 {url}")
End Select
Next
End Select
程式碼產生以下輸出
控制檯
所有已釋出的穩定版:
6.2.1 釋出於 2022年6月15日 1:00:00,下載地址是 https://dist.nuget.org/win-x86-commandline/v6.2.1/nuget.exe
6.2.0 釋出於 2022年5月10日 21:00:00,下載地址是 https://dist.nuget.org/win-x86-commandline/v6.2.0/nuget.exe
6.1.0 釋出於 2022年2月15日 21:00:00,下載地址是 https://dist.nuget.org/win-x86-commandline/v6.1.0/nuget.exe
Select Case ShapeOf
是模式匹配專用的 Select Case
。它會改變Select Case
內Case
的含義,讓它進行模式匹配,而不會與常規的 Select Case
語法產生衝突。
匹配 JSON 物件需要用一對大括號包含 JSON 匹配模式,以下圖為例解釋。
匹配 JSON 陣列需要用一對中括號包含 JSON 匹配模式,以下圖為例解釋。
"元素1", "元素2", 345, true, false, null
。如果陣列比預期的長,匹配仍然能夠成功。任何 VB 常數表示式在這裡都能使用。包括 Date, Decimal, Nothing
。JSON 的常數(true, false, null
)也能用。
TryCast
, VB 內建的轉換規則 以及 TryParse
之類的其它轉換方式。TryParse
。
基本上每個模式匹配表示式最後都可以寫一個問號,讓表示式也能匹配空。這裡認為屬性未定義和值為空是相同的情況。下圖是一些例子。
當屬性值為空時,定義的變數具備它的預設值。
JSON 常數和模式匹配是基於模式的,類似於 LINQ 和 For Each
迴圈。它並不會綁在特定的庫和型別上。這些功能在分析或編譯程式碼時從特定的名稱空間查詢符合條件的型別,使用其中的成員。你甚至可以只裝包含 ModVB 編譯器的包,具體的模式匹配拓展包由你自己編寫。通過反編譯你的使用 JSON 常數和模式匹配的專案,你可以瞭解到如何編寫 JSON 常數拓展包和模式匹配拓展包。
ModVB 作者寫的兩篇介紹:
此文章使用 CC BY-SA 4.0 協定,範例程式碼使用 MIT 協定。
此文章目前計劃在 部落格園,GitHub,嗶哩嗶哩,百度貼吧 使用使用者名稱為 Nukepayload2 的賬號釋出。如果文章在別的地方出現,或者使用者名稱不是 Nukepayload2,則屬於被轉載。