MEF学习笔记(6):出口和元数据
出口和元數據
聲明出口解釋基本的部件輸出服務和值。有些情況由于種種原因需要用出口關聯信息。一般情況下它是用來解釋一個公共契約具體實現的性能。這可以有效地滿足允許出口或者限制出口,或者在那時導入所有可用的實現和在使用出口之前檢查它們的運行能力。
附加元數據到出口
想一下我們之前的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; } }?
?
轉載于:https://www.cnblogs.com/wangchunming/archive/2012/05/09/2491094.html
總結
以上是生活随笔為你收集整理的MEF学习笔记(6):出口和元数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 删除A数据表中的一行数据时,不小心将表名
- 下一篇: C语言实现简单线程池