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

在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. 安装pygame

    pygame的安装 我们首先要去到:http://www.pygame.org/download.shtml 下载我们所需要的软件包: 我选择的是:pygame-1.9.2a0.win32-py3.2 ...

  2. zoj 3822 Domination(2014牡丹江区域赛D称号)

    Domination Time Limit: 8 Seconds      Memory Limit: 131072 KB      Special Judge Edward is the headm ...

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

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

  4. Java Evaluate Reverse Polish Notation(逆波兰式)

    表情:: ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) ...

  5. 执行Sql块

    import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import oracle.C ...

  6. jquery的attr禁用表单元素的方法

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  7. twisted是python实现的基于事件驱动的异步网络通信构架。

    网:https://twistedmatrix.com/trac/ http://www.cnblogs.com/wy-wangyan/p/5252271.html What is Twisted? ...

  8. [Windows Phone] 如何在 Windows Phone 应用程式制作市集搜寻

    原文:[Windows Phone] 如何在 Windows Phone 应用程式制作市集搜寻 [说明] 本文说明如何在 Windows Phone 应用程式中,加入市集搜寻的功能,主要使用了 Mar ...

  9. Test SRM Level Three: LargestCircle, Brute Force

    题目来源:http://community.topcoder.com/stat?c=problem_statement&pm=3005&rd=5858 思路: 如果直接用Brute F ...

  10. Spark的分布式计算

    Spark,Spark是什么,如何使用Spark 1.Spark基于什么算法的分布式计算(很简单) 2.Spark与MapReduce不同在什么地方 3.Spark为什么比Hadoop灵活 4.Spa ...