MEF学习笔记(6):出口和元数据
出口和元數(shù)據(jù)
聲明出口解釋基本的部件輸出服務(wù)和值。有些情況由于種種原因需要用出口關(guān)聯(lián)信息。一般情況下它是用來(lái)解釋一個(gè)公共契約具體實(shí)現(xiàn)的性能。這可以有效地滿足允許出口或者限制出口,或者在那時(shí)導(dǎo)入所有可用的實(shí)現(xiàn)和在使用出口之前檢查它們的運(yùn)行能力。
附加元數(shù)據(jù)到出口
想一下我們之前的IMessageSender服務(wù)。假如我們有一些實(shí)現(xiàn),而這些實(shí)現(xiàn)與消者有關(guān)而有所不同。在我們的例子里消息是否運(yùn)行和是否安全對(duì)消費(fèi)者(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更嚴(yán)格的類型,你需要?jiǎng)?chuàng)建自己的屬性并且用[System.ComponentModel.Composition.MetadataAttribute]修飾.在這個(gè)例子里面,我們也從ExportAttribute派生,所以創(chuàng)建一個(gè)自定義出口屬性也是指定的元數(shù)據(jù)。
[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應(yīng)用于自定義的出口屬性,下一步是應(yīng)用屬性到IMessageSender實(shí)現(xiàn)。
[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仍作為一個(gè)字典,但這個(gè)事實(shí)對(duì)你來(lái)說(shuō)是無(wú)形的。
注意:你也可以創(chuàng)建元數(shù)據(jù)屬性不是他們自己出口,只需要通過(guò)創(chuàng)建使用MetadataAttributeAttribute修飾的屬性。
在這些例子里元數(shù)據(jù)會(huì)被添加到出口自定義元數(shù)據(jù)屬性被應(yīng)用的同一成員里。
進(jìn)口元數(shù)據(jù)
進(jìn)口商可以訪問(wèn)附加到出口的元數(shù)據(jù)。
使用強(qiáng)類型元數(shù)據(jù)
若要以強(qiáng)類型的方式訪問(wèn)元數(shù)據(jù)通過(guò)定義接口匹配只讀屬性 (名稱和類型)來(lái)創(chuàng)建元數(shù)據(jù)視圖。 對(duì)于我們的示例來(lái)說(shuō)將是類似于以下內(nèi)容一個(gè)接口:
public interface IMessageSenderCapabilities {MessageTransport Transport { get; }bool IsSecure { get; } }于是你可以開(kāi)始用System.Lazy<T, TMetadata>導(dǎo)入。(T是契約類型,TMetadata是你創(chuàng)建的接口)
[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;}}} }使用弱類型元數(shù)據(jù)
為了以弱類型方式訪問(wèn)元數(shù)據(jù),你使用System.Lazy<T, TMetadata>類型進(jìn)口傳遞IDictionary<string,object>元數(shù)據(jù)。然后你就可以通過(guò)作為字典的元數(shù)據(jù)屬性來(lái)訪問(wèn)元數(shù)據(jù)。
注意:一般我們推薦用強(qiáng)類型方法去訪問(wèn)元數(shù)據(jù),然而有些系統(tǒng)需要通過(guò)動(dòng)態(tài)方式訪問(wèn)元數(shù)據(jù),這也是允許的。
[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;}}} }元數(shù)據(jù)過(guò)濾和默認(rèn)屬性值
當(dāng)你選中一個(gè)元數(shù)據(jù)視圖,一個(gè)隱藏的過(guò)濾會(huì)觸發(fā)去匹配那些包含在視圖定義的元數(shù)據(jù)屬性的出口。你可以在元數(shù)據(jù)視圖里通過(guò)System.ComponentModel.DefaultValueAttribute指定屬性不需要。在下面你可以看到,我們已經(jīng)給IsSecure指定一個(gè)默認(rèn)值false。這意味著一個(gè)部件出口IMessageSender,但沒(méi)有提供IsSecure元數(shù)據(jù),但它仍然匹配。
public interface IMessageSenderCapabilities {MessageTransport Transport { get; }[DefaultValue(false)];bool IsSecure { get; } }?
?
轉(zhuǎn)載于:https://www.cnblogs.com/wangchunming/archive/2012/05/09/2491094.html
總結(jié)
以上是生活随笔為你收集整理的MEF学习笔记(6):出口和元数据的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: 删除A数据表中的一行数据时,不小心将表名
 - 下一篇: Python Mixin技术介绍