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

在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. HTML5----响应式(自适应)网页设计

    第一步:在网页代码的头部,加入一行viewport元标签 <meta name="viewport" content="width=device-width, in ...

  2. java IO流文件的读写具体实例

    IO流的分类:1.根据流的数据对象来分:高端流:所有的内存中的流都是高端流,比如:InputStreamReader  低端流:所有的外界设备中的流都是低端流,比如InputStream,Output ...

  3. python学习笔记之五:抽象

    本文会介绍如何将语句组织成函数,还会详细介绍参数和作用域的概念,以及递归的概念及其在程序中的用途. 一. 创建函数 函数是可以调用,它执行某种行为并且返回一个值.用def语句即可定义一个函数:(并非所 ...

  4. text bss data的区别

    BSS段 在采用段式内存管理的架构中,BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS ...

  5. client对象层次和0级DOM

    刚開始学了两天JS,闲着无聊,顺手画了张图

  6. Ubuntu下超实用的命令

    1. Ubuntu中查看已安装软件包的方法 sudodpkg -l 2. ubuntu系统如何查看软件安装的位置 dpkg-L软件名 实例: wwx@ubuntu:~$dpkg -L mysql-se ...

  7. Chromium

    Chromium多进程架构 多进程架构 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//Start_Here_Bac ...

  8. 冷市攻略:Listo 教你 25 今天的社会 Swift 语言 - 02 Swift Tour

    import Foundation //******************************************************************************** ...

  9. 【原创】leetCodeOj ---Remove Duplicates from Sorted List II 解题报告

    明日深圳行,心情紧张,写博文压压惊 囧 ------------------------------------- 原题地址: https://oj.leetcode.com/problems/rem ...

  10. atitit..主流 浏览器 js 发动机 内核 市场份额 attialx总结vOa9

    atitit..主流 浏览器 js 发动机  内核 市场份额 attialx总结vOa9 1. 浏览器内核 1 2. 浏览器的主要组件包含: 2 2.1. 主要组件体系结构 2 2.2. WebCor ...