上一篇学习完了MEF的基础知识,编写了一个简单的DEMO,接下来接着上篇的内容继续学习,如果没有看过上一篇的内容,

请阅读:http://www.cnblogs.com/yunfeifei/p/3922668.html。

  下面我们来主要讲解一下MEF中的导入和导出,还是上一篇的代码(这篇中,我还会贴出完整的代码),修改Program的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting; namespace MEFDemo
{
class Program
{
[Import("MusicBook")]
public IBookService Service { get; set; } static void Main(string[] args)
{
Program pro = new Program();
pro.Compose();
if (pro.Service != null)
{
Console.WriteLine(pro.Service.GetBookName());
}
Console.Read();
} private void Compose()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
CompositionContainer container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
}

修改MusicBook的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition; namespace MEFDemo
{
[Export("MusicBook",typeof(IBookService))]
public class MusicBook : IBookService
{
public string BookName { get; set; } public string GetBookName()
{
return "MusicBook";
}
}
}

注意,标红的是改动过的地方,其他地方的代码没有变,上一次我们使用的是Export的方法是[Export(typeof(IBookService))],这次前面多了一个参数,没错,这个就是一个契约名,名字可以随便起,而且可以重复,但是如果名字乱起,和其他DLL中的重复,到时候会导致程序出现很多Bug,最好按照一定的规范去起名字。

这里有了契约名以后,导入(Import)时就要指定的契约名,否则将无法找到MusicBook,Export还有一个方法是[Export("Name")],这个方法只指定了契约名,没有指定导出类型,那么默认的导出类型是object类型,在导入时导出到的对象就要为object类型,否则将匹配不到那个组件。

  到现在,我们只写了一个接口和一个实现类,导出的也是一个类,下面我们多添加几个类来看看会怎么样,为了方便大家测试,我把实现接口的类写在一个文件里面,新加几个类后,的MusicBook类文件代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition; namespace MEFDemo
{
[Export("MusicBook",typeof(IBookService))]
public class MusicBook : IBookService
{
public string BookName { get; set; } public string GetBookName()
{
return "MusicBook";
}
} [Export("MusicBook", typeof(IBookService))]
public class MathBook : IBookService
{
public string BookName { get; set; } public string GetBookName()
{
return "MathBook";
}
} [Export("MusicBook", typeof(IBookService))]
public class HistoryBook : IBookService
{
public string BookName { get; set; } public string GetBookName()
{
return "HistoryBook";
}
} }

这里添加两个类,HistoryBook和MathBook,都继承自IBookService接口,注意他们的契约名都相同,都为MusicBook,后面再详细的说这个问题,修改后的program的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting; namespace MEFDemo
{
class Program
{
[ImportMany("MusicBook")]
public IEnumerable<IBookService> Services { get; set; } static void Main(string[] args)
{
Program pro = new Program();
pro.Compose();
if (pro.Services != null)
{
foreach (var s in pro.Services)
{
Console.WriteLine(s.GetBookName());
}
}
Console.Read();
} private void Compose()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
CompositionContainer container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
}

这里需要注意的是标红的两行代码,[ImportMany("MusicBook")]还有下面的声明变成了IEnumerable<>,因为要导出多个实例,所以要用到集合,下面采用foreach遍历输出,运行的结果如下图:

一共三个,都输出了,对吧!是不是很好用啊,哈哈~~

当然,如果想全部输出,可以向第一篇文章中那样,导入和导出时都不写契约名,就会全部导出。那么写契约名有什么好处呢?

下面我们用代码说明问题,修改实现类的契约名如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition; namespace MEFDemo
{
[Export("MusicBook",typeof(IBookService))]
public class MusicBook : IBookService
{
public string BookName { get; set; } public string GetBookName()
{
return "MusicBook";
}
} [Export("MathBook", typeof(IBookService))]
public class MathBook : IBookService
{
public string BookName { get; set; } public string GetBookName()
{
return "MathBook";
}
} [Export("HistoryBook", typeof(IBookService))]
public class HistoryBook : IBookService
{
public string BookName { get; set; } public string GetBookName()
{
return "HistoryBook";
}
} }

现在三个类的契约名都不相同了,其他的代码不动,再次运行程序看看,是不是现在只输出MusicBook了,同理,修改[Import("Name")]中的契约名称,就会导入指定含有名称的类,契约名可以重复,这一以来,我们就可以用契约名给类进行分类,导入时可以根据契约名来导入。

注意:IEnumerable<T>中的类型必须和类的导出类型匹配,如类上面标注的是[Exprot(typeof(object))],那么就必须声明为IEnumerable<object>才能匹配到导出的类。

例如:我们在类上面标注[Export("Book")],我们仅仅指定了契约名,而没有指定类型,那么默认为object,此时还用IEnumerable<IBookService>就匹配不到。

那么,这种情况就要在输出是进行强制类型转换,代码如下:

[Export("MusicBook")]
public class MusicBook : IBookService
{
public string BookName { get; set; } public string GetBookName()
{
return "MusicBook";
}
}

program中的代码改变如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting; namespace MEFDemo
{
class Program
{
[ImportMany("MusicBook")]
public IEnumerable<object> Services { get; set; } static void Main(string[] args)
{
Program pro = new Program();
pro.Compose();
if (pro.Services != null)
{
foreach (var s in pro.Services)
{
var ss = (IBookService)s;
Console.WriteLine(ss.GetBookName());
}
}
Console.Read();
} private void Compose()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
CompositionContainer container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
}

这样就可以正常运行了~~

点击这里下载源码

MEF系列文章:

C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo

C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import)

C#可扩展编程之MEF学习笔记(三):导出类的方法和属性

C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

C#可扩展编程之MEF学习笔记(五):MEF高级进阶

C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import)的更多相关文章

  1. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  2. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  3. C#可扩展编程之MEF学习笔记(三):导出类的方法和属性

    前面说完了导入和导出的几种方法,如果大家细心的话会注意到前面我们导出的都是类,那么方法和属性能不能导出呢???答案是肯定的,下面就来说下MEF是如何导出方法和属性的. 还是前面的代码,第二篇中已经提供 ...

  4. C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo

    在文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门致力于解决扩展性问题的框架 ...

  5. C#可扩展编程之MEF学习

    MEF系列文章: C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import) C#可扩展编程之MEF学习 ...

  6. C#可扩展编程之MEF

    C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻 前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在 ...

  7. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  8. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  9. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

随机推荐

  1. ZKM混淆工具

    原创文章,尊重劳动,转载请标明出处 ZKM 介绍 一般使用步骤 直接使用 ZKM 脚本 使用 GUI 工具混淆,同时生成 ZKM 脚本 参考 ZKM 介绍 zkm 是一款付费的代码混淆工具. 一般使用 ...

  2. win10下搭建QTP测试环境

    安装环境win 10 64位企业版 个人学习用1..net 3.5无法安装更新问题解决:打开windows update 服务2.win10 安装中提示为了对电脑进行保护,已经阻止此应用,请与管理员联 ...

  3. mysq安装以及修改密码

    安装版MySQL是不能一键安装的,下载下来是压缩包,解压后只要进行相关配置就可以正常使用: 文章主要是记录一下,以防自己忘记: 1.首先在mysql官网--http://dev.mysql.com/d ...

  4. 解压版MySQL5.7.1x的安装与配置

    解压版MySQL5.7.1x的安装与配置 MySQL安装文件分为两种,一种是msi格式的,一种是zip格式的.如果是msi格式的可以直接点击安装,按照它给出的安装提示进行安装(相信大家的英文可以看懂英 ...

  5. android的单击监听事件

    Button button = (Button) findViewById(R.id.button1); //1.直接new出来 button.setOnClickListener(new View. ...

  6. 排序算法 ----(转载::http://blog.csdn.net/hguisu/article/details/7776068)

    1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表.即:先将序列的第1个记录看成是一个有序 ...

  7. 收缩数据库 DBCC SHRINKFILE

    /* from: http://www.cnblogs.com/blackcore/archive/2010/12/27/1917911.html */ 数据库中的每个文件都可以通过删除未使用的页的方 ...

  8. Arcgis API For IOS扩展AGSDynamicLayer新旧版API对比

    AGSDynamicLayer(ForSubclassEyesOnly) Category Reference Description This category organizes the meth ...

  9. 《python核心编程》笔记——杂项

    python语句默认会给每一行添加一个换行符,只要在最后加一个逗号就能改变这种行为 若函数里没有return就自动返回None对象 PEP(python增强提案简称)http://python.org ...

  10. winRT Com组件开发流程总结

    winRT Com组件开发: 1.编辑idl文件,winRT COM的idl文件与win32的idl文件有差异,如下: interface ItestWinRTClass; runtimeclass ...