c# MEF框架(四 MEF高级进阶)

转自:http://www.cnblogs.com/yunfeifei/p/3991330.html

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509260.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络爬虫-获取网页中的数据加伪装头,伪装成浏览器多次访问,避免单次访问导致ip被封

User-Agent&#xff1a;用户代理。是一种向访问网站提供你所使用的浏览器类型、操作系统及版本、CPU 类型、浏览器渲染引擎、浏览器语言、浏览器插件等信息的标识。UA字符串在每次浏览器 HTTP 请求时发送到服务器 Referer&#xff1a;HTTP Referer是header的一部分&#xff0c…

Unity3D求向量间的夹角

如下图 Vector3 srcPos new Vector3(0,0,0);Vector3 tarPos new Vector3(0,0,-1);Vector3 srcRot new Vector3(0,90,0);Quaternion srcQua Quaternion.Euler(srcRot);Vector3 direction tarPos - srcPos;Vector3 r Quaternion.Inverse(srcQua) * direction;Debug.Log(r);…

ActiveMQ学习

ActiveMQ: 1.设置ActiveMQ的账户密码、端口号信息 2.建立连接 3.设置消息存放位置(持久化存储jdbc、临时存储等等) 4.建立生产者 5.发送消息 6.接收者进行安全认证&#xff0c;写入账户密码、端口号信息 7.接收消息

Libevent源码分析

http://blog.csdn.net/column/details/libevent-src.html?&page2

面向切面编程--AOP

转自:https://www.cnblogs.com/qicosmos/archive/2013/04/07/3003480.html &#xff08;原创&#xff09; C 轻量级AOP框架 c11 boost技术交流群&#xff1a;296561497&#xff0c;欢迎大家来交流技术。 c中开源的AOP框架AspectC需要单独编译才能将切面的代码织入到核心逻辑代码…

IQ超过250

Problem Description 李华是一个十分聪明的同学&#xff0c;据说他的智商高达250多&#xff0c;但是今天他竟然被一道题给卡住了&#xff0c;是什么题呢&#xff1f;题目内容为&#xff1a; 给你n个数&#xff0c;然后让你判断能否用这n个数中的一些数,使他们的和组成所有的非负…

9个基于Java的搜索引擎框架

9个基于Java的搜索引擎框架 转自&#xff1a;http://blog.csdn.net/xiaomin1991222/article/details/50980573 1、Java 全文搜索引擎框架 Lucene 毫无疑问&#xff0c;Lucene是目前最受欢迎的Java全文搜索框架&#xff0c;准确地说&#xff0c;它是一个全文检索引擎的架构&a…

面向切面编程--AOP(二)

转自&#xff1a;http://www.cnblogs.com/qicosmos/p/3154174.html (原创)c11改进我们的模式之改进代理模式&#xff0c;实现通用的AOP框架 c11 boost技术交流群&#xff1a;296561497&#xff0c;欢迎大家来交流技术。 本次要讲的时候如何改进代理模式&#xff0c;具体来说是动…

TimesIsMoney

Problem Description 给你一个序列&#xff0c;有N个整数&#xff08;int以内&#xff09;&#xff0c;判断一个数在这个序列中出现几次。 Input 多组输入&#xff0c;输入到文件结尾 首先输入一个n&#xff0c;然后输入n个整数。 在输入一个m&#xff0c;代表查询的个数 &…

redis参考优秀文章

文章地址 写的很详细&#xff0c;做个记录

VS2013常用快捷键设置

Visual Studio 2013 是一个基本完整的开发工具集&#xff0c;它包括了整个软件生命周期中所需要的大部分工具&#xff0c;如UML工具、代码管控工具、集成开发环境(IDE)等等。VS 2013 中新增了很多提高开发人员工作效率的新功能&#xff0c;比如自动补全方括号、使用快捷键移动整…

多次访问redis造成redis连接总是断开的解决方案

之前做了一个新闻推荐项目用到redis&#xff0c;当把项目发布到线上去测试的时候&#xff0c;用两个redis(线上服务采用LVS负载均衡&#xff0c;两个可以切换)的时候发现开始跑的时候没有问题&#xff0c;但是过一段时间当用户访问量特别大的时候有一个redis总断开连接的问题&a…

USB Flash Drives

Description Sean is trying to save a large file to a USB flash drive. He has n USB flash drives with capacities equal to a1, a2, ..., an megabytes. The file size is equal to m megabytes. Find the minimum number of USB flash drives needed to write Seans …

VS2013+VSVIM

上世纪90年代后期出现了一股.com热潮&#xff0c;相信大家对其都有美好的回忆&#xff0c;那时使用CGI和Perl创建“动态的”网站&#xff0c;通过使用在Unix上的vi编辑器快速打字和格式化&#xff0c;这也包括后来使用的vi的复制版本vim。我可能是怀旧的&#xff0c;但我想念将…

activeMQ发送与接受消息模板代码

发送着&#xff1a; /*** */ package activemqAPI.helloworld;import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.DeliveryMode; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.MessageProducer; import …

做一个优秀的项目/产品经理

1、工作中&#xff0c;在时间、质量、成本三者之间找到平衡&#xff0c;带领团队成功研发并上线项目。 解决好以下细节问题&#xff0c;就达到一个合格IT项目经理了&#xff1a; 项目的由来&#xff0c;为什么要建立这么一个系统&#xff1f; 项目有计划吗&#xff1f; 项目的需…

一个程序员的日常书单

本想谈谈读书这个话题,想来想起觉得无从下手,就此作罢.毕业这几年,一直不敢放松,在现代这个互联网时代更加认同萧抡谓的”一日不读书,胸臆无佳想;一月不读书,耳目失清爽”.如果非要给自己找个读书的理由的话,这句诗就是最好的理由:”胸藏文墨虚若骨,腹有诗书气自华”. 与书结缘…

【转载】ssdb安装部署

转载地址&#xff1a;https://www.cnblogs.com/dyfblog/p/5894518.html ssdb是一款类似于redis的nosql数据库&#xff0c;不过redis是基于内存的&#xff0c;服务器比较昂贵&#xff0c;ssdb则是基于硬盘存储的&#xff0c;很容易扩展&#xff0c;对于一些对速度要求不是太高的…

2017年回顾及总结

从2015毕业至今&#xff0c;在c开发领域算起来已经差不多两年多的时间了。在这三年的时间里&#xff0c;涉及到的c领域的技术基本上从广度上有了一个大概的学习和认知。各个方面的知识都有所掌握&#xff0c;包括c底层实现&#xff0c;网络通信&#xff0c;并行开发&#xff0c…

Amr and Pins

Description Amr loves Geometry. One day he came up with a very interesting problem. Amr has a circle of radius r and center in point (x, y). He wants the circle center to be in new position (x, y). In one step Amr can put a pin to the border of the circl…