文章版權由作者李曉暉和博客園共有,若轉載請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/
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插件中插件注入到宿主中的過程,和插件在宿主中界面的實現。
-----歡迎轉載,但保留版權,請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/
如果您覺得本文確實幫助了您,可以微信掃一掃,進行小額的打賞和鼓勵,謝謝 ^_^