起因:工作需要針對不同類型的文件做不同的處理。打個比方,txt文件,直接列印,doc文件,直接發email,jpg文件,上傳xxx相冊站點。 其實這個問題在學習最基本的工廠模式的時候早已經解決了,稍有點面向對象基礎的,都可以寫出這樣一個文件管理器。再有新類型文件處理的時候,只需要在加一個實現類,再在 ...
起因:工作需要針對不同類型的文件做不同的處理。打個比方,txt文件,直接列印,doc文件,直接發email,jpg文件,上傳xxx相冊站點。
其實這個問題在學習最基本的工廠模式的時候早已經解決了,稍有點面向對象基礎的,都可以寫出這樣一個文件管理器。再有新類型文件處理的時候,只需要在加一個實現類,再在工廠裡面加一個if判斷,返回一個具體的處理實例即可,上層不必改動。
要幹掉工廠裡面的if,則必須要請出ioc容器了。MEF就是微軟自家的托管可擴展框架,在這裡被我用成了ioc容器,其他的功能,不求甚解。
我們先拿MEF練練手,再應用到具體的項目中。概念什麼的先扔到一邊。
新建一個控制台應用程式項目和一個類庫項目,兩個項目均引用MEF庫。類庫項目中新建三個類文件。
using System; using System.ComponentModel.Composition; namespace Parts { [Export(typeof(object))]//表示此類需要導出,導出的類型為object public class TxtFileHandler { public void Process() { Console.WriteLine("處理文本文件"); } } }
其餘的就不貼了,只是類名和輸出語句不同。
主程式:
using System; using System.ComponentModel.Composition.Hosting; namespace meftest { class Program { //容器,裝東西用的。具體裝什麼先不管。 private static CompositionContainer container; static void Main(string[] args) { //AssemblyCatalog 目錄的一種,表示在程式集中搜索 var assemblyCatalog = new AssemblyCatalog(typeof(Program).Assembly);//此處這一句實際上沒啥用,因為此程式集下沒有任何我們需要的實例(各種handler) //在某個目錄下的dll中搜索。 var directoryCatalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory,"*.dll"); var aggregateCatalog = new AggregateCatalog(assemblyCatalog, directoryCatalog); //創建搜索到的部件,放到容器中。 container = new CompositionContainer(aggregateCatalog); var exports = container.GetExports<object>();//獲得所有導出的部件(object類型的)。 foreach (var item in exports) { Console.WriteLine(item.Value); } Console.ReadLine(); } } }
編譯兩個項目,將生成的類庫文件Parts.dll拷貝到主程式的bin\debug文件夾
運行主程式:
可以看到,列印出了類名(object.ToString())。我們已經成功的創建了三個類的實例,但主程式並沒有引用這個類庫。
也可以說,我們將類的實例成功的註入到了主程式。
從這個小例子,我們可以學到,使用MEF三步驟:1、導出所需的類型(部件),2、在合適的目錄(AssemblyCatalog、DirectoryCatalog)中查找。3、將找到的部件加入到容器。
之後你就可以使用容器中的已經New好的實例了。
註意:
在TxtFileHandler這個類上面的標記[Export(typeof(object))],表示此類需要導出,而且導出的類型為object
在main函數中,var exports = container.GetExports<object>();//獲得所有導出的部件(object類型的)。
導出的類型和要獲得的類型必須一致,這種一致性被稱作為契約。
最恨天下文章一大抄,請不要轉載。