C#可扩展编程之MEF学习笔记(五):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学习笔记(五):MEF高级进阶的更多相关文章
- C#可扩展编程之MEF学习笔记(五):MEF高级进阶(转)
好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...
- odoo10学习笔记五:高级视图
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/11189279.html 树视图 tree视图表现出来是列表视图,列表中一行一纪录.可以根据每行纪录的某字段值 ...
- C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...
- C#可扩展编程之MEF学习笔记(三):导出类的方法和属性
前面说完了导入和导出的几种方法,如果大家细心的话会注意到前面我们导出的都是类,那么方法和属性能不能导出呢???答案是肯定的,下面就来说下MEF是如何导出方法和属性的. 还是前面的代码,第二篇中已经提供 ...
- C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import)
上一篇学习完了MEF的基础知识,编写了一个简单的DEMO,接下来接着上篇的内容继续学习,如果没有看过上一篇的内容, 请阅读:http://www.cnblogs.com/yunfeifei/p/392 ...
- C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo
在文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门致力于解决扩展性问题的框架 ...
- C#可扩展编程之MEF学习
MEF系列文章: C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import) C#可扩展编程之MEF学习 ...
- C#可扩展编程之MEF
C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻 前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在 ...
- java之jvm学习笔记五(实践写自己的类装载器)
java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...
随机推荐
- NLS_LANG
NLS_LANG是一个环境变量,用于定义语言,地域以及字符集属性.对于非英语的字符集,NLS_LANG的设置就非常重要. NLS:‘National Language Support (NLS)’ 当 ...
- Android安全之Https中间人攻击漏洞
Android安全之Https中间人攻击漏洞 0X01 概述 HTTPS,是一种网络安全传输协议,利用SSL/TLS来对数据包进行加密,以提供对网络服务器的身份认证,保护交换数据的隐私与完整性. ...
- SQL 重置自增列的值 批量处理
Declare @IdentityTable sysname, @IdentityColumn sysname, @TotalRows int, @i int, @Iden int, @Sql var ...
- (python) 标准模块sys和os的使用
一.sys模块 包含了系统的相关的功能.我们来学习sys.argv,它包含命令行参数. 例子:定义了一个add函数,用来实现两个整数的相加. #! coding=utf-8 # usersys.py ...
- 大前端学习笔记整理【五】关于JavaScript中的关键字——this
写在前面 工作有那么一段时间了,但是在工作中,发现自己的理论知识还是有所欠缺.特别是在javascript上,很多东西其实自己属于知道要用这个,但是不知道为什么要这么用...这种情况很是尴尬了,所以写 ...
- 16.iOS APP图标和启动画面尺寸
1. 桌面图标 (app icon) for iPhone6 plus(@3x) : 180 x 180 for iPhone 6/5s/5/4s/4(@2x) : 120 x 120 2. 系统搜索 ...
- CreateFile() 打开u盘 物理设备
//以下是用的vs2010 windows7 64 管理员权限编译成功的 HANDLE hDev = CreateFile(TEXT("\\\\.\\PhysicalDrive1" ...
- rsync+inotify实现远程数据备份
一.rsync的基本介绍 1. 什么是rsync Rsync是一款开源的.快速的.多功能的.可以实现增量的本地货远程数据镜像同步备份的优秀工具,Rsync使用与unix,linux,windows等 ...
- GDB常用命令
一. gdb使用流程 1.编译生成可执行文件 gcc -g hello.c -o hello 2.启动gdb gdb hello 3. 在main处设置断点 break main 4.运行程序 run ...
- 根据用户IP获得所在城市
运行以下代码即可<html> <head> <meta http-equiv="Content-Type" content="text/ht ...