好久没有写博客了,今天抽空继续写MEF系列的文章。有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后。

前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用的基本已经讲完了,相信大家已经能看出MEF所带来的便利了。今天就介绍一些MEF中一些较为不常用的东西,也就是大家口中的所谓的比较高级的用法。

前面讲的导出都是在每个类上面添加Export注解,实现导出的,那么有没有一种比较简便的方法呢?答案是有的,就是在接口上面写注解,这样只要实现了这个接口的类都会导出,而不需要在每个类上面都写注解。下面仅贴出接口和一个实现类的源码,其余的模仿即可:

接口代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition; namespace BankInterface
{
[InheritedExport]
public interface ICard
{
//账户金额
double Money { get; set; }
//获取账户信息
string GetCountInfo();
//存钱
void SaveMoney(double money);
//取钱
void CheckOutMoney(double money);
} }

接口上面添加了[InheritedExport]标记,没错,这个就是用在接口上面的注解。

下面给出一个实现类的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BankInterface;
using System.ComponentModel.Composition; namespace BankOfChina
{
//[Export(typeof(ICard))]
public class ZHCard : ICard
{
public string GetCountInfo()
{
return "Bank Of China";
} public void SaveMoney(double money)
{
this.Money += money;
} public void CheckOutMoney(double money)
{
this.Money -= money;
} public double Money { get; set; }
}
}

可以看到,我注释掉了导出的注解,运行后,依然可以看到,此类还是被导出了,运行结果相信看过上一篇的都已经知道了。

注意:这种方法虽然比较简单,但是只适用于比较简单的应用,看完下面后,相信大家会意识到他的不足。

下面进入今天的重点:

 MEF中如何访问某个具体的对象                                                                      

  前面我们讲过在导出的时候,可以在[Export()]注解中加入名称标识,从而识别某个具体的对象,然而这种方法只是用于页面初始化的时候就行过滤,页面打开后没有导入的就再也导入不了了,就是说我们不能在导入的集合中分辨各自的不同,所有导入的类都是没有标识的。

  为了给每一个类添加标识,我们要继承ExportAttribute类,为他添加标识属性MetaData,首先来写继承自ExportAttribute的类,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition; namespace BankInterface
{
/// <summary>
/// AllowMultiple = false,代表一个类不允许多次使用此属性
/// </summary>
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ExportCardAttribute : ExportAttribute
{
public ExportCardAttribute()
:base(typeof(ICard))
{
} public string CardType { get; set; }
}
}

代码很简单,调用的父类的构造方法,声明了一个属性CatdType,下面来添加一个接口,直接修改ICard接口文件,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition; namespace BankInterface
{
public interface ICard
{
//账户金额
double Money { get; set; }
//获取账户信息
string GetCountInfo();
//存钱
void SaveMoney(double money);
//取钱
void CheckOutMoney(double money);
} public interface IMetaData
{
string CardType { get;}
}
}

又添加了接口IMetaData,只有一个属性,注意这个属性要和刚写的ExportCardAttribute类中的属性名称要一致,这样才能实现导出。

下面利用我们的ExportCardAttribute属性来标记我们要导出的类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BankInterface;
using System.ComponentModel.Composition; namespace BankOfChina
{
[ExportCardAttribute(CardType="BankOfChina")]
public class ZHCard : ICard
{
public string GetCountInfo()
{
return "Bank Of China";
} public void SaveMoney(double money)
{
this.Money += money;
} public void CheckOutMoney(double money)
{
this.Money -= money;
} public double Money { get; set; }
}
}

在这里,我们可以设置CardType的属性,可以根据具体情况使用不同的数据类型。

现在,我们修改主程序的代码为:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using BankInterface; namespace MEFDemo
{
class Program
{
//其中AllowRecomposition=true参数就表示运行在有新的部件被装配成功后进行部件集的重组.
[ImportMany(AllowRecomposition = true)]
public IEnumerable<Lazy<ICard,IMetaData>> cards { get; set; } static void Main(string[] args)
{
Program pro = new Program();
pro.Compose();
foreach (var c in pro.cards)
{
if (c.Metadata.CardType == "BankOfChina")
{
Console.WriteLine("Here is a card of Bank Of China ");
Console.WriteLine(c.Value.GetCountInfo());
}
if (c.Metadata.CardType == "NongHang")
{
Console.WriteLine("Here is a card of Nong Ye Yin Hang ");
Console.WriteLine(c.Value.GetCountInfo());
}
}
Console.Read();
} private void Compose()
{
var catalog = new DirectoryCatalog("Cards");
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
}

这里我用到了Lazy延迟加载机制(具体参见Lazy延迟加载),可以看到我们可以根据MetaData的属性访问到CardType属性,从而判断出Card的类型,从而区分导入的类型。

点击这里,下载源码

C#可扩展编程之MEF(五):MEF高级进阶的更多相关文章

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

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

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

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

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

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

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

    上一篇学习完了MEF的基础知识,编写了一个简单的DEMO,接下来接着上篇的内容继续学习,如果没有看过上一篇的内容, 请阅读:http://www.cnblogs.com/yunfeifei/p/392 ...

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

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

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

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

  7. C#可扩展编程之MEF

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

  8. 异步编程之Promise(3):拓展进阶

    异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...

  9. C#可扩展编程之MEF(一):MEF简介及简单的Demo

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

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

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

随机推荐

  1. SQL语句转换成MapReduce的基本原理

  2. arm-linux-strip 的使用

    3.2.1    1. 移除所有的符号信息 [arm@localhost gcc]#cp hello hello1 [arm@localhost gcc]#arm­linux­strip ­strip ...

  3. PHP之最长回文串

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad"输出: "bab"注意: " ...

  4. mysql 存储过程学习

    存储过程框架 DEMILITER $$ -- 重定义符 DROP PROCEDURE IF EXISTS store_procedure$$ -- 如果存在此名的存储过程,先删除 CREATE PRO ...

  5. 重磅发布: 阿里云WAF日志实时分析上线 (含视频)

    摘要: 阿里云WAF与日志服务打通,对外开发Web访问与攻击日志.提供近实时的网站具体的日志自动采集存储.并提供基于日志服务的查询分析.报表报警.下游计算对接与投递的能力. 背景 Web攻击形势 互联 ...

  6. spring boot项目开发中遇到问题,持续更新

    1.JPA中EntityManager不能执行建表语句,提示要加事务Error:javax.persistence.TransactionRequiredException: Executing an ...

  7. 用pymysql实现的注册登录公告练习

    import pymysql #1.连接服务器 conn=pymysql.connect( host='127.0.0.1', port=3306, user='root', password='12 ...

  8. 树链剖分(模板) 洛谷P3384

    #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #d ...

  9. 滑雪 矩阵中的最长上升路径 /// 记忆化DFS || DP oj22919

    大致题意: Description 难怪Michael喜欢滑雪,因为滑雪确实很刺激.为了获得加速度,滑雪道必须向下倾斜,而且当滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一 ...

  10. VMware Workstation 10 配置Ubuntu环境

    分享到 一键分享 QQ空间 新浪微博 百度云收藏 人人网 腾讯微博 百度相册 开心网 腾讯朋友 百度贴吧 豆瓣网 搜狐微博 百度新首页 QQ好友 和讯微博 更多... 百度分享 VMware Work ...