MEF高级进阶

 

好久没有写博客了,今天抽空继续写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的类型,从而区分导入的类型。

点击这里,下载源码

MEF系列文章:

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

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

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

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

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

 
分类: ASP.NET

MEF高级进阶的更多相关文章

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

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

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

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

  3. C#可扩展编程之MEF(五):MEF高级进阶

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

  4. 潭州学院-JavaVIP的Javascript的高级进阶-KeKe老师

    潭州学院-JavaVIP的Javascript的高级进阶-KeKe老师 讲的不错,可以学习 下面是教程的目录截图: 下载地址:http://www.fu83.cn/thread-283-1-1.htm ...

  5. 高级进阶DB2(第2版)——内部结构、高级管理与问题诊断

    <高级进阶DB2(第2版)——内部结构.高级管理与问题诊断> 基本信息 作者: 牛新庄    出版社:清华大学出版社 ISBN:9787302323839 上架时间:2013-7-3 出版 ...

  6. .Net高级进阶,在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码?

    本文将通过场景例子演示,来通俗易懂的讲解在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码. 通过一系列优化最终达到两个效果,1.通过代码块来控制事务(分布式事务),2.通过委托优化Tran ...

  7. 《Android高级进阶》读书笔记

    <Android高级进阶>是据我所知的市面上唯一一本技术工具书,比较的高大全,作者的目的是为了对全领域有个初步的概念 No1: 在Android系统中,拥有事件传递处理能力的类有以下三种 ...

  8. Git log diff config高级进阶

    Git 历史相关和 git config 高级进阶 前一段时间分享了一篇<更好的 git log>简要介绍怎么美化 git log 命令,其中提到了 alias命令,今天再继续谈谈 git ...

  9. [总]Android高级进阶之路

    个人Android高级进阶之路,目前按照这个目录执行,执行完毕再做扩展!!!!! 一.View的绘制 1)setContentView()的源码分析 2)SnackBar的源码分析 3)利用decor ...

随机推荐

  1. 打印到类阵列的给定序列的所有排列的n皇后问题

    题目例如以下:Given a collection of numbers, return all possible permutations. For example, [1,2,3] have th ...

  2. SWI-Prolog

    上个月突然看到Prolog这门语言,它特殊的语法吸引了我,但是经过我一段时间的学习,发现它也不像网络上传说的那样神奇,不过我依然对它很感兴趣,有前辈说Prolog本身并不强大,但是用来作为一门辅助语言 ...

  3. 打包静默安装参数(nsis,msi,InstallShield,InnoSetup)

    原文:打包静默安装参数(nsis,msi,InstallShield,InnoSetup)[转] 有时我们在安装程序的时候,希望是静默安装的,不显示下一步下一步,这编访问来教大家如何来操作,现在常用的 ...

  4. ViewPager用法

    第一图:          页面中填充内容是随机关键词飞入和飞出动画效果,随后会更新,如今请先无视吧 ---2015-02-27--- 两年后最终更新了,网上都能搜到的,哎 无奈太懒http://bl ...

  5. wikioi 1002 旁路

    意甲冠军:这个问题刚开始的问题,有错误的含义,原桥始建于一条直线.无论多么遥远. 思维:dfs寻求答案的第一个问题.然后做最小生成树,双方不能大桥将设置INF即可了.然后假设用到INF的边就加上0即可 ...

  6. Android一些解决方案内存问题(一)

    通常我们遇到内存问题时,,解决方案一般有以下的例子: 1.做一些处理上的内存引用,经常使用软引用.加强引用.弱引用: 2.加载在内存中的照片时,它可以处理直接在内存,例如:压缩边界. 3.内存的动态恢 ...

  7. 控制执行流程——(Java学习笔记三)

    if-else     控制程序流程最基本的形式 格式: if(boolean - expresion){ statement } 或 if(boolean - expresion){ stateme ...

  8. 面向对象三大特征之继承(extends)——Java笔记(六)

    继承:            从一般到特殊的关系,是一种拓展关系,子类对象是父类的一种,也可称为”is a“的关系 泛化:         把子类里的共性抽取到父类里的来的过程 特化:         ...

  9. JavaScript编写了一个计时器

    初学JavaScript,用JavaScript编写了一个计时器. 设计思想: 1.借助于Date()对象,来不断获取时间点: 2.然后用两次时间点的毫秒数相减,算出时间差: 3.累加时间差,这样就能 ...

  10. ubuntu文本界面乱码的中国解决方案

    问题: 文本界面乱码中国 解决方式: 非常easy.安装fbterm就OK! 详细例如以下: 安装命令:sudo apt-get install fbterm xfonts-xqy 然后执行:sudo ...