繁體中文
English 简体中文 繁體中文
Methodox 首頁

教程——Pure 的基本用法

目錄

  1. 庫的使用
  2. 實用工具
  3. 高階主題

1. 庫的使用

1.1 庫的型別

Pure 2 支援從以下來源匯入庫,優先順序如下:

  1. Pure 2 自訂庫/程式碼片段/巨集。
  2. (開發中)(Divooka 包):按名稱(或通過別名)。
  3. NuGet:按名稱。
  4. 特定的 DLL 檔案。

語法都是一樣的:Import(Library)。在幕後,它會編譯所需的 DLL 並自動載入。

有時某些 NuGet 包編譯出的 DLL 名稱與 NuGet 包名不同。在這種情況下,你可能需要使用 Import(Library as DLLName) 語法。我們希望在未來的更新中自動解決這個問題。

2. 實用工具

2.1 Notebook 程式(目前僅在 Windows 上可用)

除了 Pure.exe 之外,還有一個單獨的 Notebook.exe,它提供類似 jupyter notebook 的介面,以便更輕鬆地進行除錯和開發。

Notebook 介面僅可在 Windows 上使用——不過藉助跨平臺技術,可以很容易地為其他桌面環境開發一個。我沒有去做,因為只有我一個人在用 Pure。

警告:請注意,如果你屬於以下情況,Pure 並不適合你:1)需要執行和維護不願採用新 C# 特性的過時程式碼庫;2)對自訂庫或遺留程式碼有很強的依賴;3)只能使用 .Net Framework;4)需要長期固定使用單一執行時版本。在這些情況下,Pure 不適合你,因為 Pure 將始終更新到最新的 .Net 執行時,而在採用新特性時,向後相容性是最不被優先考慮的因素之一(儘管顯然會保證一定程度的“穩定性”)。

3. 高階主題

3.1 建立供 Pure 使用的庫

Pure 有三種可直接使用的庫:

  • 任何釋出在 Nuget 上的常規 C# Net 8 DLL。較舊版本的 .Net Core dll 也可能可以使用,但請謹慎;甚至 .Net Framework dll 也可能可以使用,但我觀察到過行為不可預測的情況。
  • 任何可以使用 Include 巨集包含的使用者編寫的指令碼。
  • 任何釋出在 Central Snippets 或類似地方的使用者分享的程式碼片段。

Pure 的預期使用場景如下:

  • Pure 提供完整的語法以及 .Net 8 執行時(C# 12)的所有標準特性
  • 在基礎之上,Pure 提供一些額外的庫/程式碼片段,以進一步簡化常見任務
  • 在此之上,Pure 原生支援庫匯入(使用 Import())和指令碼匯入(使用 Include())
  • 在擴充 Pure 的現有功能,或僅僅是圍繞可複用程式碼開發庫時,開發者會編寫真正的 C# 類庫專案,並將其以 DLL 形式提供,最終在 Pure 中使用。

因此,為 Pure 建立庫非常簡單——就像建立任何標準 C# 庫一樣。預設情況下,在 Pure 中匯入時,DLL 模組中所有包含公共類的名稱空間都會被匯入。

庫可以通過遵循以下約定來提供豐富的執行時行為(所有約定都不需要依賴 Pure 2 的執行時),這些約定在使用 Import() 匯入時生效:

  1. 當庫程式集中提供了名為 Main 的靜態類時,它的所有靜態成員都將在全域可用;
  2. 如果提供了名為 Pure2LibraryOptions 的靜態類,則可以使用幾個參數來改變庫的載入行為:1)public static bool DefaultNamespaceImport = true 指定是否預設匯入所有包含公共類的名稱空間;2)public static string[] TopLevelClasses = ["Main"] 指定哪些類應在匯入時公開其所有成員,這等同於使用 Main,或作為其替代方案(當我們有多個類希望在全域級別匯出名稱時很有用)。

故障排除

Pure 使用 Net 8 編寫。然而,在載入外部 DLL 時,目前只能安全地假定開箱即用地支援 Net Standard 2.0 以及可能的 Net Core 3.1 上下文(即直接載入 Net 8 dll 可能無法立即工作)。例如,即使平臺(如 win64)受支援,System.Data.Odbc 也會丟擲“Platform not Supported”異常——導致問題的是執行時。一個臨時的變通方法是:在開發外掛/庫時,所有外掛都應以 Net Standard 2.0+、Net Core 3.1+ 或 Net Framework 4.6.1+ 為目標。實際上,問題並不在於作為託管上下文的 Net 8——執行時確實是 8.0.0(在 Roslyn 中),而且 CSharpREPL(我們的參考直譯器)可以毫無問題地使用 System.Data.Odbc(在 .Net 7 的情況下),所以我們應該能夠載入 Net 8 程式集,只是由於我們處理 DLL 載入的方式,我們需要準確載入正確的 DLL,而不能載入一個“入口” dll。我們可以使用 CSharpREPL 找到所需的正確 DLL(例如,對於以 .Net 7 為目標的 ODBC,它應該是 AppData\Roaming\.csharprepl\packages\System.Data.Odbc.7.0.0\runtimes\win\lib\net7.0\System.Data.Odbc.dll)。在實踐中,檢視臨時的 dotnet 構建解決方案時,可以在 runtimes 資料夾下找到特定的 dll。

System.Drawing 在此平臺上不(直接)受支援。請注意,使用 ODBC 庫時也是這種情況——可能是因為它有許多執行時版本。這是因為目前“Import”無法正確利用那些可能用於重定向的 dll。一種解決方案是在構建時選擇特定的執行時,而不是以“Portable”執行時為目標。在嘗試匯入模組時,Pure 會就此類情況通知使用者。

庫編寫要求:請注意,任何正在編寫的(外掛)庫都不能(因此也不應該)直接(或間接)以 .Net 8 Windows 為目標,因為託管環境(即 Pure)的目標是 .Net 8(未指定 Windows 作為目標)。解決方案是將此類元件隔離出來,並作為子程序觸發(因此需要某種資料傳輸或 IPC)。

3.2 Visual Studio 開發(完整 C# 專案)

對於快速、迭代、按需的開發,建議使用上文 2.1 節中介紹的 Notebook 程式。

對於稍微複雜一些的指令碼,可以使用 Visual Studio 進行除錯。(對於更高階的應用,建議使用正式的 C#)。請注意,建議將所有內容儲存在單個檔案中,並且不要將 csproj 和 sln 檔案提交到版本控制。

使用 .Net 8 建立一個 C# 主控台專案,同時確保關閉 Do not use top level statements(不使用頂級語句)選項。(如果使用命令列,也可以直接在指令碼資料夾中執行 dotnet new console)

VSDevSetup_Step1 VSDevSetup_Step2

如果你不想處理 null 值,可以選擇在 .csproj 檔案中指定 <Nullable>disable</Nullable>,如下所示:

VSDevSetup_Step3

要在此環境中引用 Pure 庫,只需將 Nuget 源設定為指向 Pure 的安裝資料夾,其中包含一個存放 Nuget 包的資料夾。

VSDevSetup_Step4

之後,安裝包的方式與任何其他 C# 專案一樣。

VSDevSetup_Step5

完成此設定後,你就可以直接在 Visual Studio 中編寫和除錯 Pure 指令碼:

VSDevSetup_Step6

請注意以下幾個顯著區別:

  1. 你將無法使用 Import,它會自動尋找庫並設定靜態 using。
  2. C# 頂級語句要求型別定義(例如 record)位於所有其他函式和語句的底部,而在 Pure 中可以放在任何位置。
  3. 你需要顯式宣告 using static System.Console; 才能將這些名稱公開到檔案作用域,而在 Pure 中這是自動完成的。

以下是完整的指令碼:

// Notice `Import(PackageName)` macro is only available in Pure
Import(ODBC)
using static System.Console;
using static ODBC.Main;

DSN = "SQLITE";
Row[] rows = Select<Row>("""
    SELECT *
    FROM MyTable
    """);
foreach (var row in rows)
    WriteLine(row.Name);
public record Row(string Name, double Value);

將 C# 專案轉換為 Pure 指令碼時,請注意以下區別:

// Import(ODBC)

using static System.Console;
using static ODBC.Main;

// Include(MyScript.cs)
string[] Arguments = new string[] { "--help" };

其中:

  1. Import() 和 Include() 不起作用,但可以使用 Nuget 和專案檔案達到同樣的效果。
  2. 在 C# 和 Pure 中,using 語句都必須位於指令碼頂部。
  3. 需要定義一個輔助的 string[] Arguments,否則它由 Pure 提供。

另有一段影片介紹瞭如何將 Pure 指令碼轉換為 C# 專案。