基於 SailingEase WinForm Framework 開發優秀的客戶端應用程式(2:開始搭建模組化的程式框架)
本系列文章以 SailingEase WinForm Framework 為基礎進行設計並實現,但其中的設計理念及方法,亦適用於任何型別的客戶端應用程式的設計與開發。
目錄:
SailingEase WinForm Framework
其實這是從 IDE 專案中提取出來的一個純開發框架,它沒有使用者管理、許可權管理之類的現成功能,而是提供純開發角度的開發框架,概括來說提供了以下幾方面的功能:
a.宿主程式(殼)與功能模組(外掛)的載入、排程、通訊等實現;
b.不同外掛之間在完全接耦合的基礎上,同步/非同步呼叫、狀態響應等機制的實現;
c.外掛之間在程式碼層面完全沒有互相引用關係,可以實現在缺少任意外掛的情況下啟動應用,即使他們在UI層有交集;
d.支援模組間的依存關係定義;
d.事件聚合器,用於在完全解耦的條件下,釋出及訂閱事件;
d.宿主程式提供了統一的主選單及右鍵選單的註冊/吊銷/狀態控制機制;
e.宿主程式提供了統一的視窗排程/載入/銷燬功能;
f.宿主程式提供了統一的日誌記錄、異常捕獲,Web頁面互操作等功能;
g.基於 GDI+ 自行實現的控制元件包,提供了高度的可擴充套件性;
h.基於zip格式的檔案包管理器(基於zip的自定義檔案格式,讀取或寫入指定的流);
i.對http、xml、磁碟io、反射、加解密等操作的增強與封裝;
j.其它……
第二章節:開始搭建模組化的程式框架
在前文中,我們概述了基於 SailingEase Winform Framework 的客戶端應用程式的架構設計,和模組化應用程式的設計理念,本章節將具體闡述模組化應用程式的搭建方法。
應用程式的結構
我們先從檢視的角度,直觀的分解一個客戶端應用程式的框架:
應用程式宿主(白底部分),提供了主視窗的預設實現,並向功能模組開放各種基礎服務,和檢視部分緊密相關的有兩部分:
1)主選單/工具欄控制器;
允許各功能模組,向宿主註冊主選單或子選單專案,或工具欄專案。
通過統一資源識別符號的方式提供介面,不需要功能模組提供任何檢視層面的實現。過去有一些程式,是直接把子模組的工具欄選單做成使用者控制元件註冊到宿主中,這種方式簡單易實現,但是效能和可擴充套件性,穩定性都比較差。通過統一資源標示符來註冊並更新選單或工具欄的狀態,可以從非常細的粒度上解耦UI層,舉例來說,我可以實現傳統風格的主程式選單外觀,或OFFICE2016風格的側滑式選單,都只需要更新主視窗實現即可,模組完全不受影響。從穩定性上來說,模組沒有許可權參與宿主程式的UI組織,就能在這一方面避免模組本身的問題導致宿主程式崩潰。最後是效能問題,主程式通過較好的程式碼實現,統一註冊並更新選單或工具欄的狀態,可達到最好的效能。這一細節的狀態實現,將在後文中詳細闡述。
2)工作區管理器,包含檢視控制器及排程工具;
我們將主程式的多文件區域,定義為“工作區”。在工作區中,可以呈現許多不同型別的子視窗:
1)以Tab頁形式呈現的主文件視窗;
2)以側滑方式在左側、右側、或底部顯示的工具視窗;
3)浮動的工具視窗;
工作區服務介面可以幫助模組初始化、檢索或者啟用已經存在的視窗檢視。
什麼是視窗排程服務呢?除了不同視窗間的狀態切換等,大家可以看一看 Visual Studio,留意他的主選單和工具欄,會隨著文件視窗的切換而有所不同,在入門級的客戶端程式開發中,程式設計師一般會直接在視窗的焦點事件中去顯示或隱藏相關聯的選單或工具欄,以主動的方式去操作。
在 SailingEase Winform Framework 中,工作區的視窗排程服務會負責這一行為,根據當前的活動視窗,自動切換關聯選單或工具欄的狀態。
相關的幾個基本介面設計:
大體上可以望文知義,不再贅述。
框架中實際提供的與工作區相關的介面還有許多,基本的頂層設計包括:
載入程式和容器
使用 SailingEase WinForm Framework 構建應用程式時,首先必須初始化幾個核心複合服務。這就引入了載入程式。它可以執行發生複合所需的全部功能。它類似於應用程式的 Main 方法。
對於容器,指的是控制反轉 (IoC) 容器/依賴關係注入 (DI) 容器。容器起著關鍵作用。容器儲存著應用程式中使用的所有服務,負責在需要的位置注入這些服務。
在配置容器的同時,還會自動註冊幾個核心服務(如事件聚合器),載入程式允許覆蓋其中的任何服務,如果在載入程式中覆蓋 ConfigureContainer 方法,即可註冊自己的模組載入程式。
定義並實現一個模組
在基於 SailingEase Winform Framework 的應用程式中,定義一個模組非常簡單快速,通常只需要5分鐘時間即可把模組的基本框架搭建起來。
這是一個模組定義的示例,StartPageModule.cs 是實現 IModule 介面的類。此介面僅包含一個方法,稱為 Initialize。如果把載入程式看作應用程式的 Main 方法,那麼此處的 Initialize 方法就是模組的 Main。
在該模組的建構函式中,我們取得 IUnityContainer 容器,事件聚合器 IEventAggregator ,以及工作區服務 IWorkbenchService。
IUnityContainer,IEventAggregator 和 IWorkbenchService 它們究竟從何而來?我是否要將邏輯硬編碼到模組的初始化程式碼中?
答案是“否”。載入模組時,SailingEase Winform Framework 自動將模組需要的服務從容器中解析出來,注入到模組的建構函式中,如果我們需要在模組初始化時獲得其它服務,只需在建構函式中直接加入引數即可。
模組的載入
模組的載入,可以通過 App.config 檔案的方式配置,也可以通過程式碼直接配置好,不允許釋出版使用者自行修改。
我們以在程式碼中定義模組為例,在載入程式中,通過覆蓋方法 GetModuleCatalog 即可載入所需的模組,理論上來說,你可以在此基礎上實現任意方法的模組載入邏輯。
將模組載入到宿主中,並啟動應用程式之後,即可完成一個最簡單的 SailingEase Winform 應用程式。
在下一章節中,我將進一步介紹多個模組的應用程式的構建方法,並闡述他們之間的通訊、排程、狀態響應的方法。
歡迎加我QQ交流探討,共同學習:279060597,另外我在南京,有南京的朋友嗎?