.NET Core 3.0中的WinForms创建集中式拉取请求中心
Windows 窗體(或簡稱 WinForms),多年來被用于開發具有豐富和交互式界面的基于 Windows 的強大應用程序。
各類企業對這些桌面應用程序的投入量非常巨大,每月有大約 240 萬開發人員使用 Visual Studio 創建桌面式應用。
利用和擴展現有WinForms代碼資產的好處無疑極具吸引力,但還有其他好處。
WinForms 拖放式設計器體驗使用戶能夠構建功能齊全的 UI,而不需要任何特殊知識或培訓。
WinForms 應用程序易于部署和更新,可獨立于 Internet 連接工作,并且可以在不向 Internet 公開配置的本地計算機上運行,提高了安全性。
一直到最近,WinForms 應用程序都還依然只能使用完整的 .NET Framework 進行構建,但 .NET Core 3.0 預覽版的發布改變了這一現狀。
.NET Core 的新功能和優點不再局限于 Web 開發。
通過.NET Core 3.0 WinForms增加了一些功能,比如更易于部署、更高的性能、對.NET Core 特有的NuGet 包的支持、.NET Core 命令行接口 (CLI) 等等。
本文將介紹使用這些功能的諸多好處、它們的重要性以及如何在WinForms應用程序中使用它們。
讓我們直接開始構建第一個 .NET Core 3.0 WinForms 應用程序。
在本文中,我將構建一個應用程序,用于檢索并顯示托管在 GitHub 上的其中一個開源 Microsoft 存儲庫的開放式拉取請求。
第一步是安裝最新版本的 Visual Studio 2019 和 .NET Core 3.0 SDK,之后便可使用 .NET Core CLI 命令來創建新的 WinForms 應用程序。
在添加 .NET Core 支持之前,WinForms 應用程序無法實現這一點。
即將發布的是一個新的 Visual Studio 模板,用于創建針對 .NET Core 3.0 的 WinForms 項目。
由于模板目前尚未發布,因此現在讓我們通過運行以下命令生成一個名為 PullRequestHub 的新 WinForms 項目:
為了確保項目成功創建,請導航到 dotnet new 命令創建的新目錄,使用 CLI 構建并運行項目,如下所示:
由于可以訪問 .NET Core CLI,因此也可以訪問要還原、運行和構建的命令。在運行之前,請嘗試還原和構建命令,如下所示:
這些命令的工作方式與在 .NET Core Web 應用程序的命令行中運行時的工作方式相同。請注意,在執行 dotnet run 命令時,它實際上會在執行應用之前執行還原和構建命令 (bit.ly/2UCkEaN)。現在讓我們運行項目,通過在命令行輸入 dotnet run 對其進行測試。
成功!你剛剛創建了第一個 .NET Core WinForms 應用程序。
運行時,將看到屏幕上出現一個帶有“Hello .NET Core!”文本的窗體。
在進一步向應用程序添加邏輯之前,讓我們花一點時間來討論 Visual Studio 中 WinForms 設計器視圖的當前狀態。
設置 .NET Core WinForms 應用的設計器
在 Visual Studio 中打開 CLI 生成的項目時,可能會注意到缺少某些功能。最值得注意的是,目前沒有為 .NET Core WinForms 應用程序提供設計器視圖。雖然有計劃提供此功能,但尚未完成。
幸運的是,有一個解決方案可讓你至少在添加本機支持之前訪問設計器。現在,可創建包含 UI 文件的 .NET Framework 項目。
通過這種方式就可以使用設計器編輯 UI 文件,然后 .NET Core 項目將引用 .NET Framework 項目中的 UI 文件。這使你能夠利用 UI 功能,同時仍然在 .NET Core 中構建應用程序。
以下是我為項目執行操作的方法。
除了所創建的 PullRequestHub 項目之外,還需要添加一個在 .NET Full-Framework 版本上運行的新 WinForms 項目。
將此項目命名為 PullRequestHub.Designer。創建新項目后,從 .NET Core 項目中刪除 Form1 文件,只保留 Program.cs 類。
導航到 PullRequestHub.Designer 并將窗體文件重命名為 PullRequestForm。
現在將編輯 .NET Core 項目文件,并添加以下代碼,將兩個項目中的文件關聯起來。這還將負責處理將來創建的任何其他窗體或資源:
保存項目文件后,將看到 PullRequestForm 文件出現在解決方案資源管理器中,你將能夠與它們進行交互。
如果要使用 UI 編輯器,需要確保從 .NET Core 項目中關閉 PullRequestForm 文件,并從 .NET Framework 項目中打開 PullRequestForm 文件。
更改將在兩者中進行,但僅 .NET Framework 項目提供編輯器。
構建應用程序
讓我們開始向應用程序中添加一些代碼。為了從 GitHub 檢索開放式拉取請求,我需要創建一個 HttpClient。
這就是 .NET Core 3.0 的用武之地,因為它提供了對新 HttpClientFactory 的訪問權限。全框架版本中的 HttpClient 存在一些問題,包括使用 using 語句創建客戶端的問題。HttpClient 對象將被釋放,但底層套接字在一段時間內不會被釋放,默認情況下為 240 秒。如果套接字連接保持打開狀態 240 秒,并且系統中的吞吐量很高,則系統可能會使所有空閑套接字達到飽和。發生這種情況時,新請求必須等待套接字釋放,這可能對性能產生一些非常嚴重的影響。
HttpClientFactory 有助于緩解這些問題。首先,它提供了一種在更中心位置預先配置客戶端實現的更簡單方法。它還為你管理 HttpClients 的生命周期,因此你不會遇到前面提到的問題。我們來了解如何在 WinForms 應用程序中執行此操作。
使用此新功能的最佳和最簡單的方法之一是通過依賴項注入。依賴項注入,或更普遍的控制反轉,是一種將依賴項傳遞到類中的技術。它也是減少類耦合和簡化單元測試的絕佳方法。例如,你將看到如何在程序啟動時創建 IHttpClientFactory 的實例,以便稍后在窗體中使用該對象。在以前的 .NET 版本中,這在 WinForms 中不太容易實現,這就是使用 .NET Core 的另一個優勢。
在 Program.cs 中,將創建一個名為 ConfigureServices 的方法。在本方法中,創建新的 ServiceCollection,以便可通過依賴項注入來使用服務。
需要先安裝最新的這兩個 NuGet 包:
然后添加圖 1 中所示的代碼。
這將創建一個要在窗體中使用的新 IHttpClientFactory。
結果會得到一個客戶端,可以顯式地使用它來處理涉及 GitHub API 的請求。
圖 1 創建新的 IHttpClientFactory
接下來,需要將實際的窗體類 PullRequestForm 注冊為單一實例。在本方法的末尾處,添加以下行:
然后,需要創建 ServiceProvider 的實例。在 Program.cs 類的頂部,創建以下屬性:
現在有了 ServiceProvider 屬性,請在 ConfigureServices 方法的末尾處添加一行來構建 ServiceProvider,如下所示:
最后,完整的 ConfigureServices 方法應類似于圖 2 中的代碼。
圖 2 ConfigureServices 方法
現在,需要在啟動時將窗體與容器連接起來。
應用程序運行時,這將調用 PullRequestForm 并提供可用的必要服務。
將 Main 方法更改為以下代碼:
感覺很棒!現在已完成所有連接。在 PullRequestForm 構造函數中,注入剛連接好的 IHttpClientFactory 并將其分配給本地變量,如以下代碼所示:
現在有了 HttpClient,可使用它來調用 GitHub 以檢索拉取請求、問題等。這也使得后續幾個步驟略微棘手。來自 HttpClient 的調用將為異步請求,如果你一直在使用 WinForms,你就知道接下來該怎么做。接下來必須處理線程,并將調度更新發送到 UI 線程。
為了開始檢索所有拉取請求,需在視圖中添加一個按鈕。通過這種方式,可在將來添加更多存儲庫或更多存儲庫組進行檢查。使用連接的設計器,將按鈕拖到窗體上,并將文本重命名為“Microsoft”。
在此過程中,給按鈕取一個更具含義的名稱,如 RetrieveData_Button。需要綁定到 RetrieveData_Button_Click 事件,但需要使用此代碼將其設置為異步:
在此處,需要調用檢索開放式 GitHub 拉取請求的方法。但首先,由于現在正在處理異步調用,因此必須連接 SynchronizationContext。可通過添加新屬性并使用以下代碼更新構造函數來完成此操作:
接下來,創建一個模型并將其命名為 PullRequestData,以便可以輕松地反序列化請求。相關代碼如下:
最后,創建一個名為 GetPullRequestData 方法。在本方法中,將向 GitHub API 發出請求并檢索所有開放式拉取請求。將反序列化 JSON 請求,因此請將最新版本的 Newtonsoft.Json 包添加到項目中。
代碼如下:
現在可使用 RetrieveData_Button_Click 方法調用此方法。獲得所需的數據列表后,為每個標題創建標簽列表,以便在窗體上顯示。
獲得標簽列表后,可在 UpdateUI 方法中將它們添加到 UI 中。
圖 3 顯示了此步驟。
圖 3 從 RetrieveData_Button_Click 進行調用
然后,UpdateUI 方法將使用 synchronizationContext 更新 UI,如下所示:
如果運行應用程序并單擊 Microsoft 按鈕,UI 將和 GitHub 上 dotnet/winforms 存儲庫中的所有開放式拉取請求的窗體一起更新。
現在輪到你了。正如本文的標題所說,為了使它成為一個真正的集中式拉取請求中心,讓我們更新此示例,以便從多個 GitHub 存儲庫中進行讀取。
這些存儲庫不需要來自 Microsoft 團隊,盡管觀察它們的進程十分有趣。
例如,微服務體系結構非常常見,在其中你可能擁有許多組成整個系統的存儲庫。鑒于一般而言,不長時間將分支和拉取請求單獨存儲是一個好主意,這樣的工具可以提高對開放式拉取請求的見解并提高整個系統的質量。
可設置一個 Web 應用,但又得擔心部署、運行、身份驗證等問題。
使用 . NET Core 中的 WinForms 應用程序,你無需擔心任何此類問題。
現在讓我們來看看使用 .NET Core 構建 WinForms 應用的最大優勢之一。
打包應用程序
過去,部署新的或更新的 WinForms 應用程序可能會導致與主機上安裝的 .NET Framework 版本相關的問題。通過 .NET Core 則可以獨立部署應用并從單個文件夾運行應用,而不依賴于計算機上安裝的 .NET Framework 版本。
這意味著用戶無需安裝任何內容;他們可以僅運行應用程序。通過 .NET Core 還可以一次更新和部署一個應用,因為其包版本不會相互影響。
對于本文中的示例應用,需要為其獨立打包。請注意,獨立應用程序會更大,因為它們包含 .NET Core 庫。如果要部署到安裝了 .NET Core 最新版本的計算機中,則無需獨立部署應用。相反,可通過利用已安裝的 .NET Core 版本來減小已部署應用的大小。當不希望應用程序依賴于它將運行的環境時,可使用獨立選項。
若要在本地打包應用程序,需要確保在設置中啟用了開發人員模式。嘗試運行打包項目時,Visual Studio 將進行提示并提供設置的鏈接,但若要直接啟用它,請轉到 Windows 設置,按 Windows 徽標鍵并搜索“設置”。在搜索框中鍵入“面向開發人員的設置”并選擇它。將看到啟用開發人員模式的選項。選擇并啟用此選項。
大多數情況下,如果以前打包過 WinForms 應用程序,那么創建獨立包的步驟則看起來比較熟悉。首先,創建一個新的 Windows 應用程序打包項目。將新項目命名為 PullRequestHubPackaging。當系統提示選擇目標和最低平臺版本時,請使用默認值并單擊“確定”。右鍵單擊應用程序并為 PullRequestHub 項目添加引用。
添加引用后,需要將 PullRequestHub 項目設置為入口點。完成后,在下次構建時很可能會看到以下錯誤:“如果 SelfContained 為 true,則項目 PullRequestHub 必須在項目文件中指定 RuntimeIdentifiers。”
若要修復此錯誤,請編輯 PullRequestHub.csproj 文件。在打開本項目文件時,你會注意到使用 .NET Core 的另一個優點,這是因為該項目文件現在使用的是新的輕量級格式。在基于 .NET Framework 的 WinForms 項目中,項目文件將更詳細地包含顯式默認值和引用,并將 NuGet 引用拆分為 packages.config 文件。新的項目文件格式會將包引用引入到項目文件中,從而可以在一個位置管理所有依賴項。
在本文件的第一個 PropertyGroup 節點中,添加以下行:
運行時標識符用于標識運行應用程序的目標平臺,并由 .NET 包用來表示 NuGet 包中特定于平臺的資產。
添加該標識符后,構建就應該成功了,可將 PullRequestHubPackaging 項目設置為 Visual Studio 中的啟動項目。
指示項目是獨立的設置是 PullRequestHubPackaging.wapproj 文件中需要注意的一點。文件中需要注意的代碼部分如下:
在此處,可看到 DesktopBridgeSelfContained 選項已設置為 true,這使得 WinForms 應用程序可以與 .NET Core 二進制文件一起打包。
運行該項目時,它會將文件轉儲到“win-x86”的文件夾中,該文件夾的路徑與此類似:
在 win-x86 文件夾中你會注意到有許多 DLL,這些 DLL 包含獨立應用運行所需的所有文件。
你更有可能需要將應用部署為旁載應用程序或將其上載到 Microsoft Store。旁載將使用 appinstaller 文件進行自動更新。
從Visual Studio 2017 Update 15.7 開始支持這些更新。
此外,還可以創建支持提交到 Microsoft Store 進行分發的包。
Microsoft Store 隨后會處理應用的所有代碼簽名、分發和更新。
除了這些選項之外,還有一些正在進行的工作可以將應用程序打包成單個可執行文件,從而無需使用 DLL 填充輸出目錄。
其他優點
通過 .NET Core 3.0,還可以利用 C# 8.0 的功能,包括可為 null 的引用類型、接口上的默認實現、使用模式切換語句的改進以及異步數據流。
若要啟用 C# 8.0,請打開 PullRequestHub.csproj 文件并將以下行添加到第一個 PropertyGroup:
使用 .NET Core 和 WinForms 的另一個優點是兩個項目均為開源。
這使得你可以訪問源代碼、提交 bug、共享反饋并成為貢獻者。
請查看 github.com/dotnet/winforms上的 WinForms 項目。
.NET Core 3.0 旨在為企業和公司在 WinForms 應用程序中進行的投資注入新的活力,而 WinForms 應用程序會繼續保持高效、可靠且易于部署和維護。
開發人員可以利用新的 .NET Core 特定類(如 HttpClientFactory)、采用 C# 8.0 功能(如可為 null 的引用類型)和打包獨立應用程序。
還可以訪問 .NET Core CLI 以及 .NET Core 附帶的所有性能改進。
原文地址:https://msdn.microsoft.com/zh-cn/magazine/mt833442
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結
以上是生活随笔為你收集整理的.NET Core 3.0中的WinForms创建集中式拉取请求中心的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET开发框架(三)-高可用服务器端设
- 下一篇: asp.net core 自定义异常处理