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

在Export上附加Metadata

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

使用ExportMetadataAttribute

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

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks; namespace ExportMetadataSample
{
class Program
{
[ImportMany]
public IEnumerable<IMessageSender> Senders { get; set; }
static void Main(string[] args)
{
Program p = new Program();
p.Compose();
foreach (var sitem in p.Senders)
{
IEnumerable<ExportMetadataAttribute> ems = sitem.GetType().GetCustomAttributes<ExportMetadataAttribute>(false);
foreach (var eitem in ems)
{
Console.WriteLine(eitem.Name+","+eitem.Value);
}
Console.WriteLine("----------------------");
}
Console.ReadKey();
}
void Compose()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
interface IMessageSender
{
void Send(string msg);
}
[Export(typeof(IMessageSender))]
[ExportMetadata("transport","smtp")]
class EmailSender : IMessageSender
{
public void Send(string msg)
{
Console.WriteLine("Email sent:" + msg);
}
}
[Export(typeof(IMessageSender))]
[ExportMetadata("transport","smtp")]
[ExportMetadata("secure",null)]
class SecureEmailSender : IMessageSender
{
public void Send(string msg)
{
Console.WriteLine("Secure Email sent:" + msg);
}
}
[Export(typeof(IMessageSender))]
[ExportMetadata("transport","phone_network")]
class SMSSender : IMessageSender
{
public void Send(string msg)
{
Console.WriteLine("SMS sent:" + msg);
}
} }

效果如下:

使用自定义的导出特性

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

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks; namespace ExportMetadataSample
{
class Example
{
[ImportMany]
IEnumerable<Lazy<IMessageSender,IMessageSenderCapabilities>> Senders { get; set; }
static void Main()
{
Example e = new Example();
e.Compose();
foreach (var sitem in e.Senders)
{
Console.WriteLine(sitem.Metadata.Transport+","+sitem.Metadata.IsSecure);
Console.WriteLine("----------------------");
}
Console.ReadKey();
}
void Compose()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
interface IMessageSender
{ }
[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 IMessageSenderCapabilities
{
MessageTransport Transport { get; }
bool IsSecure { get; }
}
[MessageSender(Transport = MessageTransport.Smtp)]
public class EmailSender : IMessageSender
{
public void Send(string msg)
{
Console.WriteLine("Email sent:" + msg);
}
}
[MessageSender(Transport = MessageTransport.Smtp, IsSecure = true)]
public class SecureEmailSender : IMessageSender
{
public void Send(string msg)
{
Console.WriteLine("Secure Email sent:" + msg);
}
}
[MessageSender(Transport = MessageTransport.PhoneNetWork)]
public class SMSSender : IMessageSender
{
public void Send(string msg)
{
Console.WriteLine("SMS sent:" + msg);
}
}
}

为了以一种强类型的方式访问元素据,可以通过定义一个匹配只读属性的接口来创建一个元数据视图。然后,你可以开始用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. hdu 2082 生成函数

    主题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2082 找单词 Time Limit: 1000/1000 MS (Java/Others)    Me ...

  2. FluentData

    FluentData微型ORM 最近在帮朋友做一个简单管理系统,因为笔者够懒,但是使用过的NHibernate用来做这中项目又太不实际了,索性百度了微型ORM,FluentData是第一个跳入我眼睛的 ...

  3. 自定义ComboBox,简简单单实现

    private void Button_Click(object sender, RoutedEventArgs e) { Popup1.PlacementTarget = TesTextBox; P ...

  4. HTTP代理与SPDY协议(转)

    原文出处: fqrouter HTTP代理是最经典最常见的代理协议.其用途非常广泛,普遍见于公司内网环境,一般员工都需要给浏览器配置一个HTTP代理才能访问互联网.起初,HTTP代理也用来翻越“功夫网 ...

  5. 优化数据页面(18)——标注keyword

    优化数据页面(18)--标注keyword 设计要点:优化数据页面.界面设计.美化exce 秀秀:事实上俺认为,相同是数据项,它们的重要程度也不同. 阿金:嗯? 秀秀:每一行数据时描写叙述一条信息的, ...

  6. iOS8互动的新通知

    iOS8一旦远程通知想必大家都很熟悉.不要做过多的描述在这里,直接推出iOS8交互式远程通知. 再看互动的通知电话,显示的形式                  如今来看一下详细实现方式 一.通过调用 ...

  7. 基于KMP与Levenshtein模糊匹配算法的银行联行号查询(转)

    在人民银行那里,每个银行的每一个营业网点都有自己唯一的银行联行号,根据这个号码能快速定位一间银行具体的分支行,就像根据一个身份证号码能快速确定一个人一样.例如汇款时,汇款单上要求填写收款人开户行,然后 ...

  8. WebPack实例与前端性能优化

    [前端构建]WebPack实例与前端性能优化   计划把微信的文章也搬一份上来. 这篇主要介绍一下我在玩Webpack过程中的心得.通过实例介绍WebPack的安装,插件使用及加载策略.感受构建工具给 ...

  9. .net 一些常用的工具来破解

    在.net  我们经常提到破 Reflector\SimpleAssemblyExplorer和CFF Explore几个工具. 我们有一个非常简单的Windows Form方案,例如,说他们如何使用 ...

  10. BZOJ 2006 NOI2010 超级钢琴 划分树+堆

    题目大意:给定一个序列.找到k个长度在[l,r]之间的序列.使得和最大 暴力O(n^2logn),肯定过不去 看到这题的第一眼我OTZ了一下午... 后来研究了非常久别人的题解才弄明确怎么回事...蒟 ...