標籤:winform blog http java 使用 io 資料 for
1.背景
一般的WinForm中通過C#內建的Event機制便能很好的實現事件的註冊和分發,但是,在外掛程式系統中卻不能這麼簡單的直接用已有的類來完成。一個外掛程式本不包含另外一個外掛程式,它們均是獨立解耦的,實現外掛程式和外掛程式間的通訊還需要我們設計出一個事件引擎來完成這個需求。
目前很多進階語言中基本都實現了觀察者模式,並進行了自己的封裝。比如C#中的delegate和event組合,java awt中的Event和addActionListener組合,Flex中的Event、addEventListener、dispatchEvent等。
不過這裡如果要實現外掛程式系統的事件機制,需要重新自己利用觀察者模式來進行設計。而且還將涉及到泛型這個概念。
2.知識準備2.1觀察者模式
這裡先給出觀察者模式的UML圖:
可以把觀察者模式理解為兩個部分:
(1)Obesrver(觀察者):每個觀察者均有自己的行為方式,但是他們均繼承於同一個基類,此基類中定義了一個所有繼承觀察者均有的行為觸發方法。
(2)Subject(觸發者):觸發者即是被觀察者,在Subject中一定會有一個容器來儲存與觸發者相關的觀察者,因為包含觀察者容器,所以Subject方法中提供了註冊和登出的方法。同時Subject中一定有一個觸發方法,當調用此方法時,便會遍曆裝有觀察者的容器,Obeserver類再利用多態特性實現了每個觀察者特有的行為。
2.2. 泛型
泛型是具有預留位置(型別參數)的類、結構、介面和方法,這些預留位置是類、結構、介面和方法所儲存或使用的一個或多個類型的預留位置。
事件機制中的通訊資料因為不能確定為某種具體資料,在實現中,統一用泛型來代替。
3.以一個需求為線索
項目中需要在外掛程式處理完影像後,將處理完的影像的地址、名稱以及類型通知給宿主。然後宿主根據得到的訊息和資料,將處理完後的影像展現出來。
4.設計完整的可匯出的觸發者(Subject)部分
這部分設計的UML圖如下所示:
4.1設計單個觸發者(Subject)
代碼中實現了觀察者容器、注入和發布部分。
4.2 設計要傳遞的內容(data)
我的項目中需要將外掛程式處理完影像後,將處理完的影像的地址、名稱以及類型通知給宿主。於是我將這樣設計我的事件中包含的資料:
4.3 設計觸發者子類(ConcreteSubject)
具體的要傳遞的資料是對應具體的觸發者的。我們可以有多種多樣的事件,而每種觸發者將對應一種事件,所以這裡需要設計多個觸發者子類。針對3.1.2中說的外掛程式處理完影像後的觸發事件,這裡給出實現的代碼:
4.4 設計MEF中的契約(Contract)
4.5 設計觸發者容器(EventAggregator)
觸發者容器中包含了所有的觸發者,並且提供了擷取容器中具體觸發者的方法,即GetEvent方法。代碼中還給出了Export標籤,這是為了讓其他外掛程式和組件載入後能夠將觸發者容器注入其中。這樣需要將某個方法注入到一個具體的事件上時,則只需在觸發者容器中通過GetEvent方法得到該觸發者,然後將方法再subscribe到這個觸發者中。
4.6整體結構
5. 設計完整的可注入的觀察者(Observer)部分5.1將觸發者容器(EventAggregator)注入
5.2 將Observer註冊到對應的觸發者(Subject)中
首先獲得需要註冊入的ConcreteSubject,然後將Observer注入其中,這裡的Observer是繼承於Action的。
6.設計事件觸發(invoke)部分6.1將觸發者容器(EventAggregator)注入
這裡同樣需要將EventAggregator注入到事件被觸發的模組中。
6.2 觸發機制的實現
首先獲得需要觸發的觸發者(ConcreteSubject),然後將需要傳遞的資訊執行個體化,最後觸發這個事件(Publish)。
7.總結
到這裡,我已經把我的MEF外掛程式系統中的事件機制解析完了。其實說到底就是一個觀察者模式的實現,只是在這個模式的基礎上做了一個封裝。在下一節中,我將主要講解MEF外掛程式中外掛程式注入到宿主中的過程,和外掛程式在宿主中介面的實現。