首页 > 其他 > 详细

MEF 编程指南(六):导出和元数据

时间:2014-04-23 00:00:35      阅读:689      评论:0      收藏:0      [点我收藏+]

声明导出解释了部件导出服务的基础知识和价值观(Values)。有时候出于种种原因,导出关联信息是非常必要的。通常,用于解释关于功能公共契约的具体实现。允许导入满足约束要求的导出,或者导入所有可用的实现并且在导出前在运行时检查他们的功能。

 
为导出附加元数据(Attaching Metadata to an Export)
 
考虑到 IMessageSender 服务更早引入。假设我们有一些实现,和相关的消费者实现(Consumer Of The Implementations)有差异。对于我们的示例,消息的传送(Transport)和是否安全(Secure)对于消费者(导入部件)都是重要的信息。
 
使用 ExportMetadataAttribute 特性
 
所有我们需要做的事情是使用 [System.ComponentModel.Composition.ExportMetadataAtrribute] 附加这些信息。
 
bubuko.com,布布扣
    [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);
        }
    }
 
    public interface IMessageSender
    {
        void Send(string message);
    }
bubuko.com,布布扣

 

 
 
使用自定义导出特性(Using a Custom Export Attribute)
 

为了使用比 ExportMetadata 更强类型,需要创建自定义特性并且用 [System.ComponentModel.Composition.MetadataAttribute] 标识。本例中也继承自 ExportAttribute 特性,因而创建自定义导出特性并且指定了元数据。
 
 
 
bubuko.com,布布扣
    [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
    }
 
    public interface IMessageSender
    {
        void Send(string message);
    }
bubuko.com,布布扣

 

 
 
以上,MetadataAttribute 应用于自定义导出特性。下一步是将特性应用 IMessageSender 实现:
 
bubuko.com,布布扣
    [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);
        }
    }
bubuko.com,布布扣

 

 

这就是在导出端需要做的全部事情。MEF 机制下依然会填充一个字典(Populating A Dictionary),但是这对用户不可见。


注意:你也可以创建没有自身导出的元数据特性,通过创建一个使用 MetadataAttribute 标识的特性。在这些情况下,元数据会被添加到有相同成员的应用自定义元数据特性的导出。
 
 
导入元数据(Importing Metadata)
 
导入部件能访问附加到导出的元数据。
 
 
使用强类型元数据(Using Strongly-typed Metadata)
 
 
为了访问强类型的元数据,通过定义匹配只读属性(名称和类型)的接口创建元数据视图。对于我们示例,像下面的接口:
 
    public interface IMessageSenderCapabilities
    {
        MessageTransport Transport { get; }
        bool IsSecure { get; }
    }

 

 

然后,就可以使用 System.Lazy<T, TMetadata> 类型开始导入,其中 T 是契约类型,TMetadata 是创建的接口。
 
 
 
bubuko.com,布布扣
    public class HttpServerHealthMonitor
    {
        [ImportMany]
        public Lazy<IMessageSender, IMessageSenderCapabilities>[] Senders { get; set; }
 
        public void SendNotification()
        {
            Compose();
            foreach (var sender in Senders)
            {
                if (sender.Metadata.Transport == MessageTransport.Smtp && sender.Metadata.IsSecure)
                {
                    var messageSender = sender.Value;
                    messageSender.Send("Server is fine");
 
                    break;
                }
            }
        }
 
        private void Compose()
        {
            //var container = new CompositionContainer();
            //container.ComposeParts(this, new EmailSender());
            AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var container = new CompositionContainer(catalog);
            container.ComposeParts(this);
        }
    }
bubuko.com,布布扣

 

 
 
使用弱类型元数据(Using Weakly-Typed Metadata)
 

为了访问弱类型的元数据,使用 System.Lazy<T, TMetadata> 类型传递 IDictionary<string, object> 元数据给导入。然后,可以通过 Dictionary 的元数据属性访问元数据。

 
注意:通常,我们建议通过强类型方法访问元数据,然后有些系统需要动态形式访问元数据,弱类型允许这种方式。
 
 
元数据过滤和 DefaultValueAttribute 特性(Metadata Filtering and DefaultValueAttribute)
 
When you specifiy a metadata view, an implicit filtering will occur to match only those exports which contain the metadata properties defined in the view. You can specify on the metadata view that a property is not required, by using the System.ComponentModel.DefaultValueAttribute. Below you can see where we have specified a default value of false on IsSecure. This means if a part exports IMessageSender, but does not supply IsSecure metadata, then it will still be matched.
 
 
原文地址:

MEF 编程指南(六):导出和元数据,布布扣,bubuko.com

MEF 编程指南(六):导出和元数据

原文:http://www.cnblogs.com/JavCof/p/3679224.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!