博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实战MEF(5):导出元数据
阅读量:4500 次
发布时间:2019-06-08

本文共 3182 字,大约阅读时间需要 10 分钟。

如何理解元数

我们可以把元数据理解为随类型一起导出的附加信息。有时候我们会考虑,把元数据随类型一并导出,增加一些说明,使得我们在导入的时候,可以多一些筛选条件。

默认的类型导出带有元数据吗

上面的内容我说得比较简洁,也许您不是很理解,不要紧,在编程里面,很多东西我们都是写了代码后才理解的。所以,我的理论功底比较差,最不擅长的就是长篇大论,还是从代码中看吧。

我们首先要弄清楚一下问题:在我没有手动去添加元数据的默认导出类型,是否带有元数据。为了使代码更简单,这里我直接把一个类导出,而不编写公共接口了。

这里我们直接编写一个类,然后直接导入这个类型即可:

示例代码定在当前程序集中,可以在AssemblyCatalog范围查找。

AssemblyCatalog的Parts属性在智能提示中没有出现(从ComposablePartCatalog类继承下来,可能是因为虚方法没有被重写,所以没有在智能提示中显示出来),不过的确有这个属性,通过枚举Parts访问每个导出的组件类,而在ExportDefinitions属性中的每个ExportDefinition对象都有一个Metadata属性,它就是每个导出的元数据,为字典类型(IDictionary<string, object>),key是字符串类型,value是任意对象(Object)。

运行应用程序后,我们会看到如下图所示的内容:

这个例子表明,在默认情况下,导出是带有元数据的,从上面的运行结果可以猜到默认的元数据是用于说明导出组件的类型的。

 

如何导出元数据?

要导出元数据,除了对目标类型应用ExportAttribute特性外,还要用ExportMetadataAttribute特性来定义元数,在定义时遵循字典结构,即构造函数的两个参数分别代表key和value。如下面代码:

这两个元数据标记本组件的版本为200,作者是小王。我们知道元数据是IDictionary<string, object>字典结构,这就好办,我们在导入的时候使用Lazy<T, TMetadata>,以前我们用过Lazy<T>,现在因为带了元数据,所以就用Lazy<T, TMetadata>,然后让TMetadata的类型为IDictionary<string, object>就可以了。示例代码如下:

AssemblyCatalog cat = new AssemblyCatalog(typeof(Program).Assembly);// 组装CompositionContainer container = new CompositionContainer(cat);Program p = new Program();try{container.ComposeParts(p);// 显示元数据if (p.f_task.Metadata.ContainsKey("Ver")){Console.WriteLine("版本号:{0}。", p.f_task.Metadata["Ver"].ToString());}if (p.f_task.Metadata.ContainsKey("Author")){Console.WriteLine("作者:{0}。", p.f_task.Metadata["Author"].ToString());}Console.Write("\n\n");// 测试调用p.f_task.Value.OutPut();}catch(Exception ex){Console.WriteLine(ex.Message);}finally{container.Dispose();}

 

好了,运行一下,如图所示,我们已经把元数据也导入了。

 

还有另一种较为复杂的元数据导出导入方式,那就是自己实现的强类型元数据。我们来动手做做。

  1. 定义一个表示元数据的公共接口,名为ICustMetadata。
[MetadataViewImplementation(typeof(MyCustMetaData))]public interface ICustMetadata{int Ver { get; } //版本string Author { get; } //作者}

 

在定义接口时,并加上MetadataViewImplementation特性,且指明哪些类将实现该接口。

2、上面我们指定了实现ICustMetadata的类为MyCustMetaData,所以接下来我们要定义这个类。

public class MyCustMetaData:ICustMetadata{IDictionary
m_dic;// 构造函数public MyCustMetaData(IDictionary
_pDic){this.m_dic = _pDic;} public int Ver{get{if (m_dic.ContainsKey("Ver")){return Convert.ToInt32(m_dic["Ver"]);}return -1;}} public string Author{get{if (m_dic.ContainsKey("Author")){return m_dic["Author"].ToString();}return string.Empty;}}}

 

注意:定义元数据视图类时,必须包含带有一个IDictionary<string, object>类型参数的构造函数,否则将无法使用。我们通过前面的内容知道元数据其实是以字典形式存在的,故传给元数据视图类的构造函数的就是元数据的原始视图,只是我们用一个类来重封装了一下而已。

4、把调用的代码修改如下:

class Program{[Import]public Lazy
f_task; static void Main(string[] args){AssemblyCatalog cat = new AssemblyCatalog(typeof(Program).Assembly);// 组装CompositionContainer container = new CompositionContainer(cat);Program p = new Program();try{container.ComposeParts(p);// 显示元数据Console.WriteLine("元数据视图类型:{0}。", p.f_task.Metadata.GetType().Name);// 显示元数据Console.WriteLine("------- 元数据如下 --------");Console.WriteLine("版本:{0}", p.f_task.Metadata.Ver);Console.WriteLine("作者:{0}", p.f_task.Metadata.Author);Console.Write("\n\n");// 测试调用p.f_task.Value.OutPut();}catch(Exception ex){Console.WriteLine(ex.Message);}finally{container.Dispose();}Console.Read();}}

 

最后就得到如下图所示的结果:

元数据的实际类型正好是我们上面定义的MyCustMetaData类。

转载于:https://www.cnblogs.com/gzskys/p/5595535.html

你可能感兴趣的文章
POJ 1067 取石子游戏
查看>>
django开发框架-view & template
查看>>
[Linux]systemd和sysV
查看>>
时间日期正则表达
查看>>
JSON.NET 简单的使用
查看>>
java 集合 HashMap
查看>>
三栏宽度自适应布局的三种方法及其优缺点
查看>>
实训作业1
查看>>
日期控件 DatePicker 在ie8不能用
查看>>
多个表左联,要返回全部的结果,解决不能用where的问题
查看>>
hibernate left join fetch 出错的问题
查看>>
ifconfig,netstat command not found
查看>>
插入多个背景音乐
查看>>
jQuery fsBanner 手风琴
查看>>
filter IE滤镜(Internet Explorer)CSS
查看>>
混凝土数学第四章之数论学习笔记
查看>>
【转载】聊聊并发(二)——Java SE1.6中的Synchronized
查看>>
mongodb学习笔记
查看>>
史记十表-卷十七-汉兴以来诸侯王年表第五
查看>>
英文外包
查看>>