在导出声明这一节中解释了部件导出服务和值的基础知识。在某些情况下,出于多种原因,关联与导出相关的信息是有必要的。通常,它被用来解释一个指定的普通契约实现的能力。这对于允许导入约束满足它的导出,或者导入此时所有可用的实现和检查它在使用导出之前在运行时的能力是很有用的。

在Export上附加Metadata

思考这个先前介绍的IMessageSender服务。假设我们有一些实现,这些实现不同的地方可能与实现的消费者(importer)有关。针对我们的例子,消息传输及其是否安全,对于实现的消费者来说是很重要的信息。

使用ExportMetadataAttribute

我们附加这信息要做的所有事情就是使用[System.ComponentModel.Composition.ExportMetadataAttribute]:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel.Composition;
  4. using System.ComponentModel.Composition.Hosting;
  5. using System.Linq;
  6. using System.Reflection;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9.  
  10. namespace ExportMetadataSample
  11. {
  12. class Program
  13. {
  14. [ImportMany]
  15. public IEnumerable<IMessageSender> Senders { get; set; }
  16. static void Main(string[] args)
  17. {
  18. Program p = new Program();
  19. p.Compose();
  20. foreach (var sitem in p.Senders)
  21. {
  22. IEnumerable<ExportMetadataAttribute> ems = sitem.GetType().GetCustomAttributes<ExportMetadataAttribute>(false);
  23. foreach (var eitem in ems)
  24. {
  25. Console.WriteLine(eitem.Name+","+eitem.Value);
  26. }
  27. Console.WriteLine("----------------------");
  28. }
  29. Console.ReadKey();
  30. }
  31. void Compose()
  32. {
  33. var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  34. var container = new CompositionContainer(catalog);
  35. container.ComposeParts(this);
  36. }
  37. }
  38. interface IMessageSender
  39. {
  40. void Send(string msg);
  41. }
  42. [Export(typeof(IMessageSender))]
  43. [ExportMetadata("transport","smtp")]
  44. class EmailSender : IMessageSender
  45. {
  46. public void Send(string msg)
  47. {
  48. Console.WriteLine("Email sent:" + msg);
  49. }
  50. }
  51. [Export(typeof(IMessageSender))]
  52. [ExportMetadata("transport","smtp")]
  53. [ExportMetadata("secure",null)]
  54. class SecureEmailSender : IMessageSender
  55. {
  56. public void Send(string msg)
  57. {
  58. Console.WriteLine("Secure Email sent:" + msg);
  59. }
  60. }
  61. [Export(typeof(IMessageSender))]
  62. [ExportMetadata("transport","phone_network")]
  63. class SMSSender : IMessageSender
  64. {
  65. public void Send(string msg)
  66. {
  67. Console.WriteLine("SMS sent:" + msg);
  68. }
  69. }
  70.  
  71. }

效果如下:

使用自定义的导出特性

为了比使用[ExportMetadata]更加强类型地到处元素据,你需要创建你自己的特性并用[Metadata]来修饰它。在这个例子中,我们也将从ExportAttribute继承,这样来创建一个自定义的也指定元素据的导出特性。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel.Composition;
  4. using System.ComponentModel.Composition.Hosting;
  5. using System.Linq;
  6. using System.Reflection;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9.  
  10. namespace ExportMetadataSample
  11. {
  12. class Example
  13. {
  14. [ImportMany]
  15. IEnumerable<Lazy<IMessageSender,IMessageSenderCapabilities>> Senders { get; set; }
  16. static void Main()
  17. {
  18. Example e = new Example();
  19. e.Compose();
  20. foreach (var sitem in e.Senders)
  21. {
  22. Console.WriteLine(sitem.Metadata.Transport+","+sitem.Metadata.IsSecure);
  23. Console.WriteLine("----------------------");
  24. }
  25. Console.ReadKey();
  26. }
  27. void Compose()
  28. {
  29. var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  30. var container = new CompositionContainer(catalog);
  31. container.ComposeParts(this);
  32. }
  33. }
  34. interface IMessageSender
  35. {
  36.  
  37. }
  38. [MetadataAttribute]
  39. [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
  40. public class MessageSenderAttribute : ExportAttribute
  41. {
  42. public MessageSenderAttribute()
  43. : base(typeof(IMessageSender))
  44. {
  45.  
  46. }
  47. public MessageTransport Transport { get; set; }
  48. public bool IsSecure { get; set; }
  49. }
  50. public enum MessageTransport
  51. {
  52. Undefined,
  53. Smtp,
  54. PhoneNetWork,
  55. Other
  56. }
  57. public interface IMessageSenderCapabilities
  58. {
  59. MessageTransport Transport { get; }
  60. bool IsSecure { get; }
  61. }
  62. [MessageSender(Transport = MessageTransport.Smtp)]
  63. public class EmailSender : IMessageSender
  64. {
  65. public void Send(string msg)
  66. {
  67. Console.WriteLine("Email sent:" + msg);
  68. }
  69. }
  70. [MessageSender(Transport = MessageTransport.Smtp, IsSecure = true)]
  71. public class SecureEmailSender : IMessageSender
  72. {
  73. public void Send(string msg)
  74. {
  75. Console.WriteLine("Secure Email sent:" + msg);
  76. }
  77. }
  78. [MessageSender(Transport = MessageTransport.PhoneNetWork)]
  79. public class SMSSender : IMessageSender
  80. {
  81. public void Send(string msg)
  82. {
  83. Console.WriteLine("SMS sent:" + msg);
  84. }
  85. }
  86. }

为了以一种强类型的方式访问元素据,可以通过定义一个匹配只读属性的接口来创建一个元数据视图。然后,你可以开始用System.Lazy<T, TMetadata>来导入,其中T是契约类型,而TMetadata是你创建的接口。输出如图:

使用弱类型元数据

为了以一种弱类型费那个事访问元素据,你通过使用System.Lazy<T, TMetadata>,并向其TMetadata泛型参数传递IDictionary<string,object>来作为元数据来导入,然后,你可以将Lazy<T,TMetadata>的Metadata转换为IDictionary<string,object>类型来访问。注意:一般情况,我们建议使用强类型来访问元数据,然而,有一些系统需要动态方式访问元数据,弱类型方式允许你这么做。

MEF初体验之六:导出和元素据的更多相关文章

  1. MEF初体验之九:部件生命周期

    理解MEF容器中部件的生命周期及其含义是非常重要的.鉴于MEF重点在开放端应用程序,这将变得尤其重要的,一旦app ships和第三方扩展开始运行,作为应用程序的开发者将很好地控制这一系列的部件.生命 ...

  2. MEF初体验之七:Using Catalogs

    MEF特性化编程模型的价值主张之一是通过catalogs动态发现部件的能力.Catalogs允许应用程序很容易地消费那些通过[Export]已经自我注册的exports. Assembly Catal ...

  3. MEF初体验之五:Lazy Exports

    在一个部件组合中,导入将触发一个部件或者多个部件的实例化,这些部件暴露了所需原请求部件的必要的导入.对于一些应用程序来说,延迟实例化-防止图结构下的递归组合-可能对于将创建一个长久复杂的开销很大而不必 ...

  4. MEF初体验之四:Imports声明

    组合部件使用[System.ComponentModel.Composition.ImportAttribute]特性声明导入.与导出类似,也有几种成员支持,即为字段.属性和构造器参数.同样,我们也来 ...

  5. MEF初体验之三:Exports声明

    组合部件通过[ExportAttribute]声明exports.在MEF中,有这么几种成员可声明exports的方式:组合部件(类).字段.属性和方法.我们来看下ExportAttribute类的声 ...

  6. MEF初体验之十二:Composition Batch

    一个MEF容器实例是不可变的.如果catalog支持改变(像观察一个目录的改变)或是如果你的代码在运行时添加或移除部件,改变都可能发生.以前,你不得不作出改变并在组合容器上调用它的组合方法.在Prev ...

  7. MEF初体验之十一:查询组合容器

    查询组合容器 组合容器暴露了几个get exports的重载方法和导出对象和对象集合.你需要注意下面的行为: 当请求单个对象实例时,如果未发现导出,一个异常将被抛出 当请求单个对象实例时,如果发现超过 ...

  8. MEF初体验之十:部件重组

    一些应用程序被设计成在运行时可以动态改变.例如,一个新的扩展被下载,或者因为其它的多种多样的原因其它的扩展变得不可用.MEF处理这些多样的场景是依赖我们称作重组的功能来实现的,它可已在最初的组合后改变 ...

  9. MEF初体验之八:过滤目录

    当在使用子容器的时候,基于某些具体标准来过滤目录可能是重要的.例如,基于部件的创建策略来过滤是很常见的.下面的代码片段演示了如何构建这种特别方法: var catalog = new Assembly ...

随机推荐

  1. ACdream: Sum

    Sum Time Limit: 2000/1000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticN ...

  2. Windows Phone开发(45):推送通知大结局——Raw通知

    原文:Windows Phone开发(45):推送通知大结局--Raw通知 为什么叫大结局呢?因为推送通知服务就只有三种,前面扯了两种,就剩下一种--Raw通知. 前面我们通过两节的动手实验,相信大家 ...

  3. cocos2d-x 3.0游戏实例学习笔记 《跑酷》第一步--- 开始界面

    说明:这里是平局:晓风残月前辈的博客.他是将泰然网的跑酷教程.用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...

  4. JS获得URL参数

    使用JavaScript获得URL在参数值 方法一: function getUrlParam(name) {      var reg = new RegExp("(^|&)&qu ...

  5. bootstrap的popover在trigger设置为hover时不隐藏popover

    使用bootstrap的popover,trigger设置为hover时,可以实现当鼠标放置到目标元素上时显示popover,可是无法实现当鼠标移动到popover上时不隐藏popover,在网上找了 ...

  6. HashMap的遍历和排序

    1.HashMap的遍历 package com.sheepmu; import java.util.HashMap; import java.util.Iterator; import java.u ...

  7. zookeeper集群的python代码测试

    上一篇已经讲解了如何安装zookeeper的python客户端,接下来是我在网上搜到的例子,举例应用环境是: 1.当有两个或者多个服务运行,并且同意时间只有一个服务接受请求(工作),其他服务待命. 2 ...

  8. cgo 随笔(golang)

    结构体应用 //结构体定义如下 // test.h struct test { int a; int b; int c; } 在golang中的调用如下: package name import &q ...

  9. SQL声明大全

    1.随机选择3记录     select top 3 * from tablename newid() 2.随机选记录     select newid(). 3.删除反复记录 1) delete f ...

  10. SRM 628 D1L3:DoraemonPuzzleGame,math,后市展望,dp

    称号:c=problem_statement&pm=13283&rd=16009">http://community.topcoder.com/stat?c=probl ...