MEF 的精髓在於插件式開發,方便擴展。
我學東西,習慣性的先搞的最簡單的Demo出來,看看有沒有好玩的東東,然后繼續深入。這個博文,不談大道理,看demo說事兒。
至於概念,請google ,大把大把的。
例如,應用程序的日志輸出到文本,后來想改為輸出到數據庫,按照傳統的辦法,需要替換項目,刪除原有的引用,增加新的引用;如果使用MEF,直接用新的dll替換原來的dll,即可搞定,這就是MEF的魅力。
下面就用簡單的例子來實現上述的需求。
1. 建立一個解決方案,然后增加如下的幾個項目
Dblog 輸出日志到數據庫的實現
TextLog 輸出日志到文本的實現
Ilog 輸出日志的接口,調用方和實現者的中間橋梁
MEFConsoleHost 控制台應用程序,模擬實用場合
MEFWPFHost WPF 應用程序,模擬實用場合
2. 先定義接口Ilog,非常簡單,就一個方法
3. 輸出到文本的實現TextLog
首先添加引用:引用剛才添加的接口Ilog 和System.ComponentModel.Composition
然后增加類TextLogService.cs,繼承接口,並實現方法。
注意 類和方法都Public。
最后定義導出[Export(typeof(ILog.ILogService))]
這個是最主要的,和普通的類庫區別也在這里
4. 輸出到數據庫的實現DbLog,實現方法同上例,輸出日志的時候區分一下。
5. 調用方MEFConsoleHost, 這個也需要增加兩個引用,
Ilog 和System.ComponentModel.Composition
主程序代碼如下:
class Program
{
[Import(typeof(ILogService))]
public ILogService CurrentLogService { get; set; }
static void Main(string[] args)
{
Program pro = new Program();
pro.Run();
}
void Run()
{
//var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory,"DbLog.dll");
var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory, "TextLog.dll");
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
CurrentLogService.Log("MEF Log Test Pass");
Console.Read();
}
}
注意兩個地方
a. 導入聲明
[Import(typeof(ILogService))]
public ILogService CurrentLogService { get; set; }
用接口來定義實例,然后增加導入聲明,和導出的相互對應
b. 建立Catalog和Container
var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory, "TextLog.dll");
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
先這么寫,隨后再深入挖掘。
6. 把所有項目的輸出都指定到同一個目錄,也就說讓dll和exe在同一目錄,運行控制台程序,輸出
TextLog: MEF Log Test Pass
7.如果我們要輸出到數據庫,把上面的catalog那一句改成
var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory,"DbLog.dll");
如果不想這么麻煩,這個目錄里面只放DbLog.dll 或者TextLog.dll ,然后把上面那句改為:
var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory);
照樣可以用。
如果兩個都在,還這么搞,那不行的,因為就定義了一個實例,同目錄有兩個dll。
好了,入門的Demo就到這里。
可以延伸開來,觸類旁通,繼續深入研究其他概念,例如其他的Catalog\Export等。