第36章外掛程式
外掛程式可以在以後給應用程式新增功能。我們可以建立乙個主機應用程式,隨時間的推移給它新增越來越多的功能--這些功能可以是開發團隊編寫的,其他**商也可以建立外掛程式,擴充套件該應用程式。
目前,外掛程式在許多不同的應用程式上使用,例如ie和visual studio。ie是乙個主機應用程式,它提供了乙個外掛程式框架,許多公司都使用這個框架提供檢視web頁面時的擴充套件程式。shockw**e flash object可以檢視帶flash內容的web頁面。
google工具欄提供了特殊的google功能,可以在ie中快速訪問。visual studio也有乙個外掛程式模型,可以用不同層次的擴充套件程式擴充套件visual studio。
定製應用程式總是可以建立外掛程式模型,以動態載入和使用程式集中的功能。利用外掛程式模型時,需要考慮許多問題。如何檢測新的程式集?
如何解決版本問題?外掛程式可以改變主機應用程式的穩定性嗎?
.net framework 3.5提供了乙個框架,用程式集來儲存和建立外掛程式。這個框架也稱為managed addin framework(maf)。
提示:外掛程式還有其他稱呼,如add-on或plug-in。
本章內容如下:
● 體系結構
● 建立簡單的外掛程式
36.1 體系結構
建立允許在執行期間新增外掛程式的應用程式時,需要處理一些問題。例如,如何找到外掛程式,如何解決版本問題,使主機應用程式和外掛程式可以獨立地公升級。要解決這些問題,有幾種方式。
本節討論外掛程式的問題和maf解決它們的體系結構:
● 外掛程式的問題
● 管道體系結構
● 發現
● 啟用
● 隔離
● 生存期
● 版本問題
36.1.1 外掛程式的問題
要建立乙個主機應用程式,動態載入以後新增的程式集,必須解決幾個問題,如表36-1所示。
表 36-1
下面**maf的體系結構,說明這個框架如何解決這些問題。maf的設計目標如下:
● 應易於開發外掛程式
● 在執行期間查詢外掛程式應很高效
● 開發主機程式應是乙個很簡單的過程,但不像開發外掛程式那麼容易
● 外掛程式和主機應用程式應獨立地公升級
36.1.2 管道體系結構
maf體系結構基於乙個包含7個程式集的管道。這個管道解決了外掛程式的版本問題。因為管道中的程式集之間的依賴性很低,所以合同、主機程式和外掛程式公升級到新版本可以完全互不干擾。
圖36-1顯示了maf體系結構的管道。其中心是合同程式集。這個程式集包含乙個合同介面,其中列出了外掛程式必須實現、可以由主機程式呼叫的方法和屬性。
合同的左邊是主機端,右邊是外掛程式端。圖中還顯示了程式集之間的依賴性。最左端的主機程式集與合同程式集沒有依賴性,外掛程式集與合同程式集也沒有依賴性,這兩個程式集都沒有實現合同定義的介面,只是有乙個對檢視程式集的引用。
主機應用程式引用主機檢視;外掛程式引用外掛程式檢視。檢視包含抽象的檢視類,該類定義的方法和屬性與合同相同。
圖36-2顯示了管道中類的關係。主機類與抽象的主機檢視類有乙個關聯,並呼叫其方法。抽象的主機檢視類由主機介面卡實現。
介面卡在檢視和合同之間建立連線。外掛程式介面卡實現了合同的方法和屬性。這個介面卡包含對外掛程式檢視的引用,把來自主機端的呼叫傳送給外掛程式檢視。
主機介面卡類定義了乙個具體的類,它派生自主機檢視的抽象基類,實現了方法和屬性。這個介面卡包含對合同的引用,把來自檢視的呼叫傳送給合同。
有了這個模型,外掛程式端和主機端可以完全獨立地公升級了,只是需要使用對映層。例如,如果主機的乙個新版本使用全新的方法和屬性,合同就仍可以保持不變,只有介面卡需要修改。也可以定義新的合同。
介面卡可以修改,也可以同時使用幾個合同。
36.1.3 發現
如何為主機應用程式查詢新外掛程式?maf體系結構使用乙個預定義的目錄結構來查詢外掛程式和管道的其他程式集。管道的組成部分儲存在這些子目錄中:
● hostsideadapters
● contracts
● addinsideadapters
● addinviews
● addins
除了addins目錄之外,其他目錄都直接包含管道特定部分的程式集。addins目錄為每個外掛程式集包含乙個子目錄。外掛程式也可以儲存在完全獨立於其他管道元件的目錄中。
管道的程式集需要使用反射來動態載入,才能獲得外掛程式的所有資訊。而且,對於許多外掛程式而言,這還會增加主機應用程式的啟動時間。因此,maf使用乙個快取記憶體,來儲存管道元件的資訊。
該快取記憶體是由安裝外掛程式的程式建立的,如果主機應用程式有管道目錄的寫入許可權,該快取記憶體就由主機應用程式建立。
給管道元件快取記憶體的資訊是呼叫addinstore類的方法來建立的。update()方法查詢還沒有列在儲存檔案中的新外掛程式。rebuild()方法用外掛程式的資訊重建完全二進位制的儲存檔案。
表36-2列出了addinstore類的成員。
表 36-2
36.1.4 啟用和隔離
addinstore類的findaddins()方法返回表示外掛程式的addintoken物件集合。使用addintoken類可以訪問外掛程式的資訊,例如名稱、描述、發布者和版本。使用activate()方法可以啟用外掛程式。
表36-3列出了addintoken類的屬性和方法。
表 36-3
乙個外掛程式可能使整個應用程式崩潰,例如ie可能因乙個失敗的外掛程式而崩潰。根據應用程式型別和外掛程式的型別,可以讓外掛程式執行在另乙個應用程式域或另乙個程序中,來避免這個問題。maf給出了幾個選項。
可以在新應用程式域或新程序中啟用外掛程式。新應用程式域還可以有有限的許可權。
addintoken類的activate()方法有幾個過載版本,在這些版本中,可以傳送載入外掛程式的環境引數。表36-4列出了不同的選項。
表 36-4
提示:應用程式域詳見第17章。
應用程式的型別也會限制可以使用的選項。wpf外掛程式目前不支援跨程序。windows forms不能在不同的應用程式域之間連線windows控制項。
下面列出呼叫addintoken的activate()方法時管道的執行步驟:
(1) 用指定的許可權建立應用程式域。
(2) 用方法把外掛程式的程式集載入到新的應用程式域中。
(3) 用反射呼叫外掛程式的預設建構函式。因為外掛程式派生於在外掛程式檢視中定義的基類,所以也載入了檢視的程式集。
(4) 接著構造外掛程式端介面卡的乙個例項。外掛程式的例項傳送給介面卡的建構函式,使介面卡能連線合同和外掛程式。外掛程式介面卡派生於基類marshalbyrefobject,所以可以在應用程式域之間呼叫。
(5) 啟用**給主機應用程式的應用程式域返回外掛程式端介面卡的乙個**。外掛程式介面卡實現了合同介面,所以該**包含合同介面的方法和實現。
(6) 主機端介面卡的例項在主機應用程式的應用程式域中構造。外掛程式端介面卡的**傳送給該建構函式。啟用**會從外掛程式令牌中查詢主機端介面卡的型別。
主機端介面卡返回給主機應用程式。
36.1.5 合同
合同定義了主機端和外掛程式端之間的界限。合同用乙個介面來定義,該定義必須派生於基介面icontract。合同必須仔細考慮,因為它根據需要支援靈活的外掛程式場景。
合同沒有版本支援,不能改變,所以外掛程式以前的實現**仍可以在新的主機程式中執行。新版本應通過定義新合同來建立。
合同的型別有一些限制,其原因是版本問題,而且應用程式域要從主機應用程式跨越到外掛程式上。型別必須是安全的,且支援版本,能在邊界(應用程式域或跨程序)之間傳送,也能在主機程式和外掛程式之間傳送。
可以用合同傳送的型別可以是:
● 基本型別
● 其他合同
● 可序列化的系統型別
● 簡單的可序列化定製型別,包括基本型別、合同,以及沒有實現**的型別
介面icontract的成員如表36-5所示。
第6章結構化程式設計基礎
在vfp互動方式下,除了通過命令視窗 系統選單和工具對vfp進行操作外,還可以通過程式方式執行較複雜的資料處理任務。vfp程式設計包括結構化程式設計和物件導向程式設計。結構化程式設計是傳統的程式設計方法,是物件導向程式設計的基礎。程式是指能夠完成一定任務的一組有序命令的集合。程式中的命令也稱為語句。...
第6章迴圈結構程式設計習題及答案
第6章迴圈結構程式設計 6 1 比較while語句 do while語句和for語句的異同。答 1 while語句 do while語句用於條件迴圈,for語句用於計數迴圈。2 while語句 for語句是先判斷迴圈條件,後執行迴圈體,如果迴圈條件一開始就不成立,則迴圈體一次也不被執行 而do wh...
第8章程式設計基礎
一 是非題。和loop作用相同,都能終止迴圈。a.對b.錯 2.自定義函式與過程檔案的不同在於自定義函式必須返回乙個值。a.對b.錯 語句只能接收字元型常量。a.對b.錯 4.不管是過程還是函式,接收引數的命令必須出現在被調程式的第一行。a.對b.錯 5.過程檔案可以由若干個過程構成,而過程必須放在...