MEF學習筆記(6):出口和中繼資料

來源:互聯網
上載者:User
出口和中繼資料

聲明出口解釋基本的組件輸出服務和值。有些情況由於種種原因需要用出口關聯資訊。一般情況下它是用來解釋一個公用契約具體實現的效能。這可以有效地滿足允許出口或者限制出口,或者在那時匯入所有可用的實現和在使用出口之前檢查它們的運行能力。

附加中繼資料到出口

想一下我們之前的IMessageSender服務。假如我們有一些實現,而這些實現與消者有關而有所不同。在我們的例子裡訊息是否運行和是否安全對消費者(importer)是重要的資訊。

使用ExportMetadataAttribute

附加這些資訊我們只需要做的就是使用[System.ComponentModel.Composition.ExportMetadataAttribute]:

public interface IMessageSender{    void Send(string message);}[Export(typeof(IMessageSender))][ExportMetadata("transport", "smtp")]public class EmailSender : IMessageSender{    public void Send(string message)    {        Console.WriteLine(message);    }}[Export(typeof(IMessageSender))][ExportMetadata("transport", "smtp")][ExportMetadata("secure", null)]public class SecureEmailSender : IMessageSender{    public void Send(string message)    {        Console.WriteLine(message);    }}[Export(typeof(IMessageSender))][ExportMetadata("transport", "phone_network")]public class SMSSender : IMessageSender{    public void Send(string message)    {        Console.WriteLine(message);    }}

使用自訂出口屬性

為了使它比ExportMetadataAttribute更嚴格的類型,你需要建立自己的屬性並且用[System.ComponentModel.Composition.MetadataAttribute]修飾.在這個例子裡面,我們也從ExportAttribute派生,所以建立一個自訂出口屬性也是指定的中繼資料。

[MetadataAttribute][AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]public class MessageSenderAttribute : ExportAttribute{    public MessageSenderAttribute() : base(typeof(IMessageSender)) { }    public MessageTransport Transport { get; set; }    public bool IsSecure { get; set; }}public enum MessageTransport{    Undefined,    Smtp,    PhoneNetwork,    Other}

上面的例子裡,MetadataAttribute應用於自訂的出口屬性,下一步是應用屬性到IMessageSender實現。

[MessageSender(Transport=MessageTransport.Smtp)]public class EmailSender : IMessageSender{    public void Send(string message)    {        Console.WriteLine(message);    }}[MessageSender(Transport=MessageTransport.Smtp, IsSecure=true)]public class SecureEmailSender : IMessageSender{    public void Send(string message)    {        Console.WriteLine(message);    }}[MessageSender(Transport=MessageTransport.PhoneNetwork)]public class SMSSender : IMessageSender{    public void Send(string message)    {        Console.WriteLine(message);    }}

這就是出口方所必須的。在引擎裡,MEF仍作為一個字典,但這個事實對你來說是無形的。

注意:你也可以建立中繼資料屬性不是他們自己出口,只需要通過建立使用MetadataAttributeAttribute修飾的屬性。

在這些例子裡中繼資料會被添加到出口自訂中繼資料屬性被應用的同一成員裡。

進口中繼資料

進口商可以訪問附加到出口的中繼資料。

使用強型別中繼資料

若要以強型別的方式訪問中繼資料通過定義介面匹配唯讀屬性 (名稱和類型)來建立中繼資料視圖。 對於我們的樣本來說將是類似於以下內容一個介面:

public interface IMessageSenderCapabilities{    MessageTransport Transport { get; }    bool IsSecure { get; }}

於是你可以開始用System.Lazy<T, TMetadata>匯入。(T是契約類型,TMetadata是你建立的介面)

[Export]public class HttpServerHealthMonitor{    [ImportMany]    public Lazy<IMessageSender, IMessageSenderCapabilities>[] Senders { get; set; }    public void SendNotification()    {        foreach(var sender in Senders)        {            if (sender.Metadata.Transport == MessageTransport.Smtp &&                 sender.Metadata.IsSecure)            {                var messageSender = sender.Value;                messageSender.Send("Server is fine");                                break;            }        }    }}

使用弱類型中繼資料
為了以弱類型方式訪問中繼資料,你使用System.Lazy<T, TMetadata>類型進口傳遞IDictionary<string,object>中繼資料。然後你就可以通過作為字典的中繼資料屬性來訪問中繼資料。

注意:一般我們推薦用強型別方法去訪問中繼資料,然而有些系統需要通過動態方式訪問中繼資料,這也是允許的。

[Export]public class HttpServerHealthMonitor{    [ImportMany]    public Lazy<IMessageSender, IDictionary<string,object>>[] Senders { get; set; }    public void SendNotification()    {        foreach(var sender in Senders)        {            if (sender.Metadata.ContainsKey("Transport") && sender.Metadata["Transport"] == MessageTransport.Smtp &&                 sender.Metadata.ContainsKey("Issecure") && Metadata["IsSecure"] == true)            {                var messageSender = sender.Value;                messageSender.Send("Server is fine");                                break;            }        }    }}

中繼資料過濾和預設屬性值

當你選中一個中繼資料視圖,一個隱藏的過濾會觸發去匹配那些包含在視圖定義的中繼資料屬性的出口。你可以在中繼資料視圖裡通過System.ComponentModel.DefaultValueAttribute指定屬性不需要。在下面你可以看到,我們已經給IsSecure指定一個預設值false。這意味著一個組件出口IMessageSender,但沒有提供IsSecure中繼資料,但它仍然匹配。

public interface IMessageSenderCapabilities{    MessageTransport Transport { get; }    [DefaultValue(false)];    bool IsSecure { get; }}

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.