MFC構造基於插件的應用系統?

我們並不是要刻意挖空一個程序的內容。這樣做的目的是尋找一個解決MFC機制臃腫的方案。結果,我們得到的是一些碎片。現在我們找到理由了,根據插件系統的一般原理,我們看到了這些碎片重新合成的可能性。有了一個最小的MFC程序,一類主窗口插件、一類文檔模板插件,問題就很清晰了。那就是:如何將這些東西拼裝起來,以形成一個真正的程序。

步驟/方法

  現在,讓我們將剝離後的碎片重新合成,以形成一個系統吧!首先:我們需要一個具有組織、加載能力的應用程序。這樣一個完整的例子可以參考我們提供的案例代碼,徹底的方案是將上述機制形成一系列Wizard並與Visual Studio集成。為此我們提供了所有這些相關的工作(在隨機光盤中提供);一旦有了程序,合成工作的基礎就建立了。

MFC構造基於插件的應用系統

  第二步:我們需要一個配置文件以便指定特定應用需要的主窗口插件以及文檔模板隊列的檢索位置。為此,一個最好的做法就是直接利用.NET程序的默認配置文件。對.NET程序而言,配置文件相當於一個局部的註冊表,不僅可以指定組件的局部檢索路徑,而且可以指定其他的定製化信息。為了合成工作的需要,在配置文件中增加如下結點:
  
  
     MainAppType = ".net"
  MainAssemblyLib = " testmainframe"
  MainAssemblyCategory= "testmainframe"
  MainFrameAssembly =
  "testmainframe.AppObject"
  >
  
  

  經過上述調整後,程序的配置文件事實上為合成工作描述了一個合成方案。一個程序可以有任意多個描述方案,當面對不同需求的時候,用戶可以形成不同的方案。由於每個.NET程序可以存儲在不同的本地目錄中,因此,你可以為每個本地目錄匹配一個不同的合成方案以此實現應用系統的多態性。

  第三步:系統通過MainAssemblyLib = "testmainframe"指定主窗口插件所在的.NET程序集名稱;MainFrameAssembly = "testmainframe.AppObject"指定加載主窗口的.NET對象的ID值。這個方法與JavaBean採用的技術十分相似,給軟件配置帶來了十分靈活的機制。由於主窗口的實現已經與程序分離了,因此,開發人員可以根據需要提供多個主窗口(理論上可以實現任意多個主窗口),甚至直接使用已存在的主窗口對象。而且,由於實現主窗口的動態鏈接庫是基於.NET框架的,因此,你甚至可以用其他.NET語言重載相關的對象。例如,如果負責加載主窗口的.NET對象中存在有針對性的“虛函數”,那麼其他開發者甚至用戶就可以重載這個對象,以實現進一步的程序定製化。一般來說,我們可以將主窗口與對應負責加載主窗口的.NET對象匹配在一起形成一個對偶對,就可以實現“通過相應的.NET對象驅動主窗口”這一驅動模型。一旦運行時可以將主窗口關聯的對象模型委託給其他對象模型系統,你的程序主體就具備了強大的“二次開發”能力。著名的VBA與Visual Studio for Application以及Visual Studio Tools for Office就是通過類似的原理實現的。

MFC構造基於插件的應用系統

  第四步:與主窗口對象不同的是,我們需要加載一個文檔模板隊列。因此,需要提供一個文檔模板的檢索機制。為此,可以在程序所在的目錄中建立一個子目錄DocTemplate,我們希望相關的文檔信息保存在這個目錄中;並且每個模板通過一個XML文件進行描述,其中指定實現文檔模板的組件庫以及負責加載模板的.NET對象ID值。當然,我們也可以建立一個全局目錄,負責保存共享的模板對象庫。這個實現在想法上很類似開源集成框架eclipse,此時每個文檔類型通過插件的形式集成到一個特定場合中的主窗口框架之中。例如,如果對象庫DocumentXDocTemplate1.dll包含一個文檔模型,且加載模型的.NET對象的ID值是DocumentXDocTemplate1.DocTemplate,那麼描述這個模型的XML文件就是象下面這樣的:
  
     DocViewID="DocumentXDocTemplate1#
  DocumentXDocTemplate1.DocTemplate"
  DocObjID = ""
  ExtDocObjID = ""
  >
  
  所有的描述文檔模板的xml文件均保存在DocTemplate目錄中,因此程序就具備了枚舉文檔模板的能力。在模板描述文件中,通過Template節點的DocViewID屬性的值指定模板對應得組件庫。這個值的格式為“xxx#yyy”,其中“xxx”指定對象庫,“yyy”指定加載模板的對象ID。例如上面的XML文件顯示組件庫DocumentXDocTemplate1.dll中.NET對象DocTemplate負責加載文檔模板的工作,即對象DocTemplate中存在一個方法,這個方法將在運行時被宿主程序激活,並將(a)中描述的代碼嵌入到宿主程序並執行。從這裡我們可以看到,程序支持的文檔類型並不一定必須在初始化的環節插入文檔模板隊列,需要的時候插入即可。

  完成上述步驟後,一個程序系統就形成了。那它可以做什麼實際的工作呢?當它在不同的運行環境下加載了相應的主窗體和文檔模板時,它的具體功能才體現了出來。你可以在需要時加載兩個完全不同的文檔模板,表現為兩個完全不同的運行態。換句話說,如果有一個通用的應用框架基礎可以一致地實現異構編程框架支持、功能邏輯的動態演化機制,那麼開發人員就可以在這個基礎之上隨心所欲地把握各種可用的技術資源,專注於豐富功能的設計和構造,而不用從頭做起。按照我們的觀點,基於文檔的程序,是個無內容的程序,只有這樣,這個程序所支持的內容才可能達到最大的飽和度。我們的軟件哲學是:在程序的具體應用場合中賦予程序以內容——首先我們希望形成一個描述方案,即制定程序的配置文件;其次,主窗口是外接的,即主窗口被實現成一個外接插件;不僅如此,所有的文檔模板均被實現成插件,這樣就使得不同場合不同配置成為可能。

MFC構造基於插件的應用系統

相關問題答案