天天看點

實戰MEF(4):搜尋範圍

在前面的文章中,幾乎每個示例我們都會接觸到擴充類的搜尋位置,我們也不妨想一下,既然是自動擴充,它肯定會有一個或者多人可供查找的位置,不然MEF架構怎麼知道哪裡有擴充元件呢?

就像我們用導航系統去查找某個地方的所有旅店一樣,正因為在該地的旅店已在資料庫中注冊了相關資訊,我們的導航系統才能查找到它,如果某家旅店沒有向導航資料庫提供任何資料,那很顯然導航系統是無法識别到它的詳細位址的。

MEF對擴充元件的查找範圍通常有三個:

  1. AssemblyCatalog:從某個程式集中查找。
  2. ApplicationCatalog:在應用程式所在的目錄下查找。
  3. DirectoryCatalog:在某個目錄下查找,如D:\\Libs。

如果你還嫌不夠的話,可以用AggregateCatalog來設定多個查找範圍。

下面我們來逐個嘗試一下。

  1. AssemblyCatalog

基于某個程式集的範圍查找,最常幹的是在目前程式集内查找,當然也可以在其他程式集中查找。隻要能得到一個Assembly對象就可以在其中查找,大家都那麼聰明,我相信大家能了解的。

下面是一個典型的做法,例子是在目前程式集中查找擴充部件的。

首先,我們定義一個用于規範擴充部件行為的接口。

實戰MEF(4):搜尋範圍

然後,寫兩個類來實作上面的接口,并将它們導出。

實戰MEF(4):搜尋範圍

在應用程式類中,用一個公共字段把它們全部導入。

實戰MEF(4):搜尋範圍

最後,在Main中進行組裝并測試調用。

實戰MEF(4):搜尋範圍

最終,程式運作結果如下圖所示。

實戰MEF(4):搜尋範圍

二、DirectoryCatalog

這一個我們可能有些陌生,因為在前面文章的示例中,我們并沒有使用過該類,但是,不要因為陌生而害怕,天有多高,你的膽子就應該有多大,陌生的東西很多時候是不複雜的,就好像我們與陌生人對話有時候反而比與熟人對話更自在。

    DirectoryCatalog類可以指定一個目錄,讓MEF在這個目錄下面尋找擴充元件,如果需要更細緻的查找,可以在DirectoryCatalog類的構造函數中指定一個搜尋字元串,這個字元串與我們平時搜尋檔案一樣,例如"ext_*",這表明隻要以ext_開頭的類庫檔案都在查找範圍内。

這一次,我們用一個WinForm應用程式來做例子,在窗體中我們拖放幾個控件,詳見下圖。

實戰MEF(4):搜尋範圍

控件布局随意,我一向主張個性化布局的,主要以下幾個重要的控件得介紹一下:

名為txtDirec的TextBox用來顯示選擇的目錄;名為cmbClass的ComboBox控件用來顯示MEF發現的擴充類的清單,名為txtResult的TextBox顯示擴充類的調用結果。

下面說一下本例的大概思路,我們先把擴充的類庫全放到一個任意檔案夾下,然後在應用程式視窗上選擇該目錄後,讓MEF架構在該目錄下發現所有擴充類型并顯示在ComboBox中。接着我們從ComboBox中選擇一個類來調用,并檢視調用結果。

  1. 我們先建一個公共類庫,這個類庫在主應用程式和所有擴充類庫都會引用,因為我們會在其中定義用于規範元件行為的"憲法"(接口)。該類庫暫名為CommonLib,代碼如下,很簡單,不超過10行。
實戰MEF(4):搜尋範圍

這個接口隻有一個方法SaySomething,待會我們分别用幾個類來實作它,每個類都獨立寫到一個類庫中。

  1. 新項一個類庫項目,名為ExtLibA,代碼如下:
實戰MEF(4):搜尋範圍

同樣道理,再建兩個類庫項目,分别是ExtLibB和ExtLibC。

實戰MEF(4):搜尋範圍
實戰MEF(4):搜尋範圍
  1. 分别生成這三個dll,還要包含一個CommonLib.dll,因為三個擴充庫都引用了它。然後把這幾個dll分别放到一個檔案夾中,大緻如下圖所示。
實戰MEF(4):搜尋範圍
  1. 回到WinForm項目,在窗體類中聲明一個字段,公有或私有都無所謂,用于導入類型。
實戰MEF(4):搜尋範圍
  1. 處理按鈕事件,浏覽目錄,并從指定目錄中尋找擴充部件,并且顯示在ComboBox中。
實戰MEF(4):搜尋範圍
  1. 處理按鈕事件,調用ComoBox中標明的擴充類型。
實戰MEF(4):搜尋範圍

然後,我們可以看看下面的執行結果。

實戰MEF(4):搜尋範圍

三、AggregateCatalog

有一天,我不小心把新的擴充類ExtLibD寫到了WinForm項目中了,就像這樣:

實戰MEF(4):搜尋範圍

然後我想,如果能保留前面的三個擴充類的同時,也自動識别我寫到WinForm項目中的擴充類,那該多好啊。不怕,.NET的強大隻有你想不到,沒有它做不到的。這時候我把目光投向AggregateCatalog類,利用它可以将多個搜尋範圍合并,我們剛才的三個擴充是通過在一個檔案夾中搜尋的,而第四個擴充是寫到WinForm項目中的,還記得前文中我們說過AssemblyCatalog類,它可以在某個程式集中尋找擴充類,是以第四個擴充類我們可以在WinForm項目所在的程式集中查找。

也就是說,我們把AssemblyCatalog範圍和DirectoryCatalog範圍進行組合。是以,把前面button1_Click的代碼改一下,變成以下這個樣子:

實戰MEF(4):搜尋範圍

用AggregateCatalog來把DirectoryCatalog和AssemblyCatalog合并起來,再傳給CompositionContainer的構造函數,這樣就能實作查找範圍的組合了。

好,現在運作一下,看看第四個擴充是不是自動被發現了?

實戰MEF(4):搜尋範圍

Good,預期的效果達到了,是不是很高興呢,喝杯咖啡得意一下吧。

不知道大家看了我這幾篇有關MEF的吹牛散文之後,會不會感歎MEF的神奇呢?不管大家會把MEF用在哪些地方,隻要記住兩個原則:

  1. 在需要某項技術時就該當機立斷,否則反受其亂。
  2. 技術運用講求靈活,無招勝有招,就像李小龍的"李三腳"一樣,切忌濫用。

好了,說了這麼多,我也口渴了,先喝杯橙汗解解渴,再見。

MEF