程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#可擴展編程之MEF學習筆記(五):MEF高級進階

C#可擴展編程之MEF學習筆記(五):MEF高級進階

編輯:C#入門知識

C#可擴展編程之MEF學習筆記(五):MEF高級進階


好久沒有寫博客了,今天抽空繼續寫MEF系列的文章。有園友提出這種系列的文章要做個目錄,看起來方便,所以就抽空做了一個,放到每篇文章的最後。   前面四篇講了MEF的基礎知識,學完了前四篇,MEF中比較常用的基本已經講完了,相信大家已經能看出MEF所帶來的便利了。今天就介紹一些MEF中一些較為不常用的東西,也就是大家口中的所謂的比較高級的用法。   前面講的導出都是在每個類上面添加Export注解,實現導出的,那麼有沒有一種比較簡便的方法呢?答案是有的,就是在接口上面寫注解,這樣只要實現了這個接口的類都會導出,而不需要在每個類上面都寫注解。下面僅貼出接口和一個實現類的源碼,其余的模仿即可:   接口代碼如下:   復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel.Composition;   namespace BankInterface {    [InheritedExport]    public interface ICard    {       //賬戶金額       double Money { get; set; }       //獲取賬戶信息       string GetCountInfo();       //存錢       void SaveMoney(double money);       //取錢       void CheckOutMoney(double money);    }   } 復制代碼 接口上面添加了[InheritedExport]標記,沒錯,這個就是用在接口上面的注解。   下面給出一個實現類的代碼:   復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using BankInterface; using System.ComponentModel.Composition;   namespace BankOfChina {    //[Export(typeof(ICard))]    public class ZHCard : ICard    {       public string GetCountInfo()       {          return "Bank Of China";       }         public void SaveMoney(double money)       {          this.Money += money;       }         public void CheckOutMoney(double money)       {          this.Money -= money;       }         public double Money { get; set; }    } } 復制代碼 可以看到,我注釋掉了導出的注解,運行後,依然可以看到,此類還是被導出了,運行結果相信看過上一篇的都已經知道了。   注意:這種方法雖然比較簡單,但是只適用於比較簡單的應用,看完下面後,相信大家會意識到他的不足。       下面進入今天的重點:    MEF中如何訪問某個具體的對象                                                                           前面我們講過在導出的時候,可以在[Export()]注解中加入名稱標識,從而識別某個具體的對象,然而這種方法只是用於頁面初始化的時候就行過濾,頁面打開後沒有導入的就再也導入不了了,就是說我們不能在導入的集合中分辨各自的不同,所有導入的類都是沒有標識的。     為了給每一個類添加標識,我們要繼承ExportAttribute類,為他添加標識屬性MetaData,首先來寫繼承自ExportAttribute的類,代碼如下:   復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel.Composition;   namespace BankInterface {    /// <summary>    /// AllowMultiple = false,代表一個類不允許多次使用此屬性    /// </summary>    [MetadataAttribute]    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]    public class ExportCardAttribute : ExportAttribute    {       public ExportCardAttribute()          :base(typeof(ICard))       {       }         public string CardType { get; set; }    } } 復制代碼 代碼很簡單,調用的父類的構造方法,聲明了一個屬性CatdType,下面來添加一個接口,直接修改ICard接口文件,代碼如下:   復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel.Composition;   namespace BankInterface {    public interface ICard    {       //賬戶金額       double Money { get; set; }       //獲取賬戶信息       string GetCountInfo();       //存錢       void SaveMoney(double money);       //取錢       void CheckOutMoney(double money);    }      public interface IMetaData    {       string CardType { get;}    } } 復制代碼 又添加了接口IMetaData,只有一個屬性,注意這個屬性要和剛寫的ExportCardAttribute類中的屬性名稱要一致,這樣才能實現導出。   下面利用我們的ExportCardAttribute屬性來標記我們要導出的類:   復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using BankInterface; using System.ComponentModel.Composition;   namespace BankOfChina {    [ExportCardAttribute(CardType="BankOfChina")]    public class ZHCard : ICard    {       public string GetCountInfo()       {          return "Bank Of China";       }         public void SaveMoney(double money)       {          this.Money += money;       }         public void CheckOutMoney(double money)       {          this.Money -= money;       }         public double Money { get; set; }    } } 復制代碼 在這裡,我們可以設置CardType的屬性,可以根據具體情況使用不同的數據類型。   現在,我們修改主程序的代碼為:   復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using BankInterface;   namespace MEFDemo {    class Program    {       //其中AllowRecomposition=true參數就表示運行在有新的部件被裝配成功後進行部件集的重組.       [ImportMany(AllowRecomposition = true)]       public IEnumerable<Lazy<ICard,IMetaData>> cards { get; set; }         static void Main(string[] args)       {          Program pro = new Program();          pro.Compose();          foreach (var c in pro.cards)          {             if (c.Metadata.CardType == "BankOfChina")             {                Console.WriteLine("Here is a card of Bank Of China ");                Console.WriteLine(c.Value.GetCountInfo());             }             if (c.Metadata.CardType == "NongHang")             {                Console.WriteLine("Here is a card of Nong Ye Yin Hang ");                Console.WriteLine(c.Value.GetCountInfo());             }          }          Console.Read();       }         private void Compose()       {          var catalog = new DirectoryCatalog("Cards");          var container = new CompositionContainer(catalog);          container.ComposeParts(this);       }    } } 復制代碼 這裡我用到了Lazy延遲加載機制(具體參見Lazy延遲加載),可以看到我們可以根據MetaData的屬性訪問到CardType屬性,從而判斷出Card的類型,從而區分導入的類型。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved