如何用 MEF 擴展應用程序

  最近在寫一篇關於如何擴展 Visual Studio 編輯器的文章時,用到了 MEF,所以打算寫一篇文章提一下這個技術點。本篇文章並不打算詳細介紹 MEF,只是一個最簡單的入門,相信您在閱讀本篇文章後,能夠迅速開發出一個可擴展的應用程序。服務器

 

簡 介

  MEF(Managed Extensibility Framework),是微軟推出的一款用於搭建可擴展應用程序的框架,起初是獨立於 .Net 發佈的,後來集成到了 .Net 4.0 中。使用該框架能夠很是輕鬆地擴展一個已發佈的應用程序的功能,連 Visual Studio IDE 中的代碼編輯器窗口也採用了MEF的思想,所以大大方便了開發人員對編輯器的擴展。框架

  MEF 可用在任何使用 .NET Framework 的地方。能夠在客戶端應用程序中使用 MEF(不管應用程序使用的是 Windows 窗體、WPF,仍是任何其餘技術),也能夠在使用 ASP.NET 的服務器應用程序中使用 MEF。編輯器

 

MEF的關鍵概念

  Importpost

  導入,這裏建議做爲一個名詞來理解,即一個接受者,它能夠接受外來的東東。就比如是下圖中的盒子,它能夠接受其它積木。this

十三孔智力盒編碼

 

  Exportspa

  導出,一樣建議以一個名詞來理解,即一個第三方的產物。它就像上圖中不一樣顏色的積木,這些積木不屬於這個盒子,可是能被放入盒子中,來豐富盒子的功能。設計

積木3d

 

  Contractcode

  協議。要想使盒子能接受積木(好比,圓柱體只能放入圓形的接口中),那這些積木必須符合必定的形狀。而這些形狀就至關因而應用程序和第三方擴展之間的一個協議。

 

  Compose

  組合(動詞),即將多個符合協議要求的部件組合在一塊兒,構成一個功能豐富的應用程序。就比如是將不一樣形狀的積木,按照接口的形狀組合在一塊兒。

  

 

它是如何工做的?

  MEF 會動態查找用戶所指定的目錄,若是發現該目錄中的程序集知足協議要求,就會啓動自身的組合引擎,而後根據不一樣的協議約定把這些擴展導入到應用程序內部。

 

用 MEF 實現一個最簡單的可擴展應用程序

  對幾個關鍵的概念清楚了以後,咱們就能夠開始實踐了。最終的效果是窗體上會動態加載某一目錄下的dll,並自動爲每一個新功能添加一個按鈕,當點擊按鈕就會執行新的功能。

最終效果

 

  首先,定義一個協議。

  這個和普通定義接口沒什麼兩樣。

1     public interface IPlugin
2     {
3         string Text { get; }
4  
5         void Do();
6     }

 

  安裝接受者 

  有了協議以後,就須要給應用程序安一個接受者。讓這個應用程序能夠經過接受者來獲取第三方擴展。MEF 提供了[Import]  [ImportMany] 兩種 attribute。 區別就是 Import 只能接受符合協議的一個擴展,而 ImportMany 能夠接受多個,並把多個擴展放入集合中。

 1     public partial class Form1 : Form
 2     {
 3         public Form1()
 4         {
 5             InitializeComponent();
 6         }
 7  
 8         [ImportMany]
 9         public IEnumerable<IPlugin> plugins;
10  
11         private void Form1_Load(object sender, EventArgs e)
12         {
13         }
14  
15     }

 


  提供一個符合協議的產物
 

  這個產物的生產過程其實就是實現接口的過程,惟一的區別是咱們要爲這個實現打上個標籤,從而告訴咱們的組合引擎這個東西是給接受者的。MEF 提供了 Export 來暗示這是一個能夠提供給接受者的產物。

 1     [Export(typeof(IPlugin))]
 2     public class MyPlugin:IPlugin
 3     {
 4         public string Text
 5         {
 6             get
 7             {
 8                 return "This is a demo";
 9             }
10         }
11  
12         public void Do()
13         {
14             MessageBox.Show(Text);
15         }
16     }

 


  發動引擎
 

  萬事俱備,就差發動了。前面說了引擎的主要做用就是把發現擴展,同時把這些擴展組合到應用程序中。

 1 private CompositionContainer _container;
 2 private void Init()
 3 {
 4     try
 5     {
 6         MyPlugin my = new MyPlugin();
 7         this._container.ComposeParts(this, my);//把擴展和實例組合在一塊兒
 8     }
 9     catch (CompositionException compositionException)
10     {
11         Console.WriteLine(compositionException.ToString());
12     }
13 }

 

  上面的代碼雖然實現了組合的功能,可是卻硬把產物給編碼進去了。要是每次開發了新的擴展,都得這樣修改應用程序代碼,那就徹底沒有使用MEF的必要了,並且也違反了開放封閉的設計原則。 

  把上面的代碼改一改。

 1 private CompositionContainer _container;
 2 private void Init()
 3 {
 4     //設置目錄,讓引擎能自動去發現新的擴展
 5     var catalog = new AggregateCatalog();
 6     catalog.Catalogs.Add(new DirectoryCatalog("D:\\plugin\\"));
 7  
 8     //建立一個容器,至關因而生產車間
 9     _container = new CompositionContainer(catalog);
10  
11     //調用車間的ComposeParts把各個部件組合到一塊兒
12     try
13     {
14         this._container.ComposeParts(this);//這裏只須要傳入當前應用程序實例就能夠了,其它部分會自動發現並組裝
15     }
16     catch (CompositionException compositionException)
17     {
18         Console.WriteLine(compositionException.ToString());
19     }
20 }

 

  上面的代碼會自動去發現擴展,而後加入到應用程序中來。你要作的只是把新擴展的程序集放入 D:\\plugin 目錄中就能夠了。是否是很方便呢?

參考資源

  Managed Extensibility Framework (MEF)

  本文源代碼下載

 

本文來源於 《如何用 MEF 擴展應用程序》

相關文章
相關標籤/搜索