MEF 編程指南(二):定義可組合部件和契約

可組合部件(Composable Parts)
 
在 MEF 內部可組合部件是一個可組合單元。可組合部件導出其餘可組合部件須要的服務,而且從其餘可組合部件導入服務。在 MEF 編程模型中,可組合部件用 [System.ComponentModel.Composition.Import] 和 [System.ComponentModel.Composition.Export] 特性標識,以便聲明導出點和導入點。可組合部件應該包含至少一個導出點。可組合部件要麼顯式添加到容器或者經過使用目錄建立。MEF 訪問默認目錄識別 Export 特性標識的可組合部件。
 
 
契約(Contacts)
 
可組合部件不直接依賴另外一個,相反依賴字符串標識的契約。每一個導出點享有一個契約,而且每一個導入點申明的他所需的契約。容器利用契約信息在導入點和導出點之間作匹配。若是沒有指定契約,MEF 會隱式使用徹底限定名的契約類型。若是傳遞了類型,也會使用徹底限定名。
 
注意:默認狀況下經過類型傳遞給契約。儘管契約能夠是任意字符串,可是可能致使歧義(Ambiguity)。好比:「Sender」可能與另外一個庫的「Sender」實現重疊。基於這個緣由,若是須要指定字符串的契約,強烈建議契約名應該包括公司名的 限定 命名空間,例如:「Contoso.Exports.Sender」。
 
如下代碼片斷,全部導出契約是等價的(Equivalent)。
 
    [Export]
    public class Exporter { }
 
    [Export(typeof(Exporter))]
    public class Exporter1 { }
 
    [Export("Chapter02.Exporter")]
    public class Exporter2 { }

 

接口/抽象契約

針對可組合部件的一種常見模式是導出接口或者抽象類型,而不是一個具體的類型。這容許導入者徹底從特定的導出實現中解耦,這致使關注點的分離。例如:下面能夠看到兩種導出 IMessageSender 的 Sender 實現。Notifier 類導入 IMessageSender 集合,調用他的 Send() 方法。新的 MessageSender 能夠很容易添加到系統。
 
 
    [Export(typeof(IMessageSender))]
    public class EmailSender : IMessageSender
    {
        public void Send(string message)
        {
            Console.WriteLine("Invoke EmailSender Send() method");
            Console.WriteLine(message);
        }
    }
 
    [Export(typeof(IMessageSender))]
    public class TCPSender : IMessageSender
    {
        void IMessageSender.Send(string message)
        {
            Console.WriteLine("Invoke TCPSender Send() method");
            Console.WriteLine(message);
        }
    }
 
    public interface IMessageSender
    {
        void Send(string message);
    }

 

 
契約程序集(Contract Assemblies)
 
使用 MEF 構建可擴展應用程序時的常見模式是發佈契約程序集。契約程序集僅包含使用者能夠擴展應用程序的契約類型。一般是接口,可是也多是抽象類。另外,契約程序集包含導入點使用的元數據(Metadata)視圖接口,以及任何自定義 MEF 導出特性。

 
注意:你必須指定特定的存在的導出接口類型(IMessageSender),不然類型(EmailSender)自己將被導出。
 
原文地址:
相關文章
相關標籤/搜索