一、MEF是什么

Managed Extensibility Framework (MEF) 是用于创建可扩展的轻量级应用程序的库。 它让应用程序开发人员得以发现和使用扩展且无需配置。 它还让扩展开发人员得以轻松地封装代码并避免脆弱的紧密依赖性。 MEF 让扩展不仅可在应用程序内重复使用,还可以跨程序重复使用。

MEF 通过组合提供了一种隐式发现它们的方法,而不是明确记录可用组件。 MEF 组件(称为一个部件),以声明方式详细说明了其依赖项(称为导入)及其可提供的功能(称为导出)。 当创建一个部分时,MEF 组合引擎利用从其他部分获得的功能满足其导入需要。

一句话,MEF就是面向接口编程的应用,接口定义行为,它把实例化类放到代码运行的时候,通过容器参数确定。

二、MEF示例

在我们国家,不管你在哪个银行办理银行卡,只要银行卡有银联标识,那么你就基本可以在任意一家银行取钱、存钱。中国银联(China UnionPay)成立于2002年3月,是经国务院同意,中国人民银行批准设立的中国银行卡联合组织,在境内的银行必须都支持银联。也就是说,中国银联定义了一些行为,例如用户可以取钱、存钱,任意一家境内银行都必须支持银联定义的行为。因此,你在任意一家银行办理银行卡后,就可以在所有的银行都进行取钱、存钱等及行为。下面我们以此为例,进行一个简单的例子:

  1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel.Composition;
4 using System.ComponentModel.Composition.Hosting;
5 using System.Linq;
6 using System.Reflection;
7 using System.Text;
8 using System.Threading.Tasks;
9
10 namespace MEF1
11 {
12 class Operation
13 {
14 static void Main(string[] args)
15 {
16 BlankOperation("CBC",300,100);
17 Console.WriteLine("------------------------------");
18 BlankOperation("BOC",888,666);
19 Console.ReadKey();
20 }
21
22 static void BlankOperation(string bankName,int saveMonenyAmout,int withdrawMoneyAmount)
23 {
24 var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
25 CompositionContainer container = new CompositionContainer(catalog);
26 var dev = container.GetExportedValue<IUnionPay>(bankName);
27 dev.SaveMoneny(saveMonenyAmout);
28 dev.WithdrawMoney(withdrawMoneyAmount);
29 }
30 }
31
32
33 interface IUnionPay
34 {
35 /// <summary>
36 /// 存钱
37 /// </summary>
38 /// <param name="amount">存钱金额</param>
39 void SaveMoneny(int amount);
40
41 /// <summary>
42 /// 取钱
43 /// </summary>
44 /// <param name="amount">取钱金额</param>
45 void WithdrawMoney(int amount);
46
47 }
48
49 /// <summary>
50 /// 工商银行
51 /// </summary>
52 [Export("CBC",typeof(IUnionPay))]
53 class ICBC : IUnionPay
54 {
55 public void SaveMoneny(int amount)
56 {
57 Console.WriteLine($"把钱存入工商银行,金额为:{amount}");
58 }
59
60 public void WithdrawMoney(int amount)
61 {
62 Console.WriteLine($"从工商银行取钱,金额为:{amount}");
63 }
64 }
65
66 /// <summary>
67 /// 建设银行
68 /// </summary>
69 [Export("CCB", typeof(IUnionPay))]
70 class CCB : IUnionPay
71 {
72 public void SaveMoneny(int amount)
73 {
74 Console.WriteLine($"把钱存入建设银行,金额为:{amount}");
75 }
76
77 public void WithdrawMoney(int amount)
78 {
79 Console.WriteLine($"从建设银行取钱,金额为:{amount}");
80 }
81 }
82
83 /// <summary>
84 /// 农业银行
85 /// </summary>
86 [Export("ABC", typeof(IUnionPay))]
87 class ABC : IUnionPay
88 {
89 public void SaveMoneny(int amount)
90 {
91 Console.WriteLine($"把钱存入建设银行,金额为:{amount}");
92 }
93
94 public void WithdrawMoney(int amount)
95 {
96 Console.WriteLine($"从建设银行取钱,金额为:{amount}");
97 }
98 }
99
100 /// <summary>
101 /// 中国银行
102 /// </summary>
103 [Export("BOC", typeof(IUnionPay))]
104 class BOC : IUnionPay
105 {
106 public void SaveMoneny(int amount)
107 {
108 Console.WriteLine($"把钱存入建设银行,金额为:{amount}");
109 }
110
111 public void WithdrawMoney(int amount)
112 {
113 Console.WriteLine($"从建设银行取钱,金额为:{amount}");
114 }
115 }
116 }

代码运行后,效果如下:

三、MEF示例改进

那如果我们在增加一个银行实现类,例如招商银行,还需要在MEF1解决方案中增加一个 “CMB”类。但如果我们的程序以及运行了,那如果在不关闭程序的前提下,还完成支持招商银行接入银联卡呢?

答案是为每个银行实现类创建一个解决方案,然后编译成dll文件,这样我们在支持招商银行接入银联时,只需要把 “CMB.dll”文件放入支持文件,就可以即不关闭主程序,还可以无缝支持招商银行接入银联:

我们把实现银联的银行的解决方案的生成目录保存在目录 “..\bin\Debug\bank\”,用于测试的解决方案和银联接口的解决方案生成目录保存在目录 “..\bin\Debug\”,编译程序,生成文件如下图:

然后测试解决方案LOC容器加载的目录也需修改为bank目录下:

 1 using ChinaUnionPay;
2 using System;
3 using System.Collections.Generic;
4 using System.ComponentModel.Composition.Hosting;
5 using System.IO;
6 using System.Linq;
7 using System.Reflection;
8 using System.Text;
9 using System.Threading.Tasks;
10
11 namespace BankOperation
12 {
13 class Program
14 {
15 static void Main(string[] args)
16 {
17 while (true)
18 {
19 Console.Write($"请输入银行名称:");
20 string name = Console.ReadLine();
21 BlankOperation(name, 300, 100);
22 Console.WriteLine("----------------------------------");
23 }
24 }
25
26 static void BlankOperation(string bankName, int saveMonenyAmout, int withdrawMoneyAmount)
27 {
28 AggregateCatalog catelog = new AggregateCatalog();
29
30 // 添加部件所在文件目录
31 string path = $"{Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath)}\\bank\\";
32 catelog.Catalogs.Add(new DirectoryCatalog(path));
33
34 // 声明容器
35 CompositionContainer container = new CompositionContainer(catelog);
36 var dev = container.GetExportedValue<IUnionPay>(bankName);
37
38 // 动作调用
39 dev.SaveMoneny(saveMonenyAmout);
40 dev.WithdrawMoney(withdrawMoneyAmount);
41 }
42 }
43 }

此时运行测试程序,运行效果如下:

此时,若在程序运行的时候添加招商银行,我们需添加招商银行的解决方案如下,然后编译生成:

 1 using ChinaUnionPay;
2 using System;
3 using System.Collections.Generic;
4 using System.ComponentModel.Composition;
5 using System.Linq;
6 using System.Text;
7 using System.Threading.Tasks;
8
9 namespace CMB
10 {
11 /// <summary>
12 /// 招商银行
13 /// </summary>
14 [Export("CMB",typeof(IUnionPay))]
15 public class Operation : IUnionPay
16 {
17 public void SaveMoneny(int amount)
18 {
19 Console.WriteLine($"把钱存入招商银行,金额为:{amount}");
20 }
21
22 public void WithdrawMoney(int amount)
23 {
24 Console.WriteLine($"从招商银行取钱,金额为:{amount}");
25 }
26 }
27 }

运行效果如下:

我们发现,使用MEF模式可以“高内聚,低耦合”,大大降低了代码的解耦,每次使一个银行接入银行的时候,完全不影响其他银行的正常业务操作。

关于.NET中的控制反转(二)- 依赖注入之 MEF的更多相关文章

  1. 轻松了解Spring中的控制反转和依赖注入(二)

    紧接上一篇文章<轻松了解Spring中的控制反转和依赖注入>讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作. 类 ...

  2. Spring中的控制反转和依赖注入

    Spring中的控制反转和依赖注入 原文链接:https://www.cnblogs.com/xxzhuang/p/5948902.html 我们回顾一下计算机的发展史,从最初第一台计算机的占地面积达 ...

  3. 轻松了解Spring中的控制反转和依赖注入(一)

    我们回顾一下计算机的发展史,从最初第一台计算机的占地面积达170平方米,重达30吨,到现如今的个人笔记本,事物更加轻量功能却更加丰富,这是事物发展过程中的一个趋势,在技术领域中同样也是如此,企业级Ja ...

  4. 在DoNetMVC中使用控制反转和依赖注入【DI】

    本次是在MVC5中使用Autofac 第一步:程序包管理器控制台 Install-Package Autofac.MVC5 引入nuget包 这样成功之后,会在引用中出现两个DLL,分别是Autofa ...

  5. .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整-控制反转和依赖注入的使用

    再次调整项目架构是因为和群友dezhou的一次聊天,我原来的想法是项目尽量做简单点别搞太复杂了,仅使用了DbContext的注入,其他的也没有写接口耦合度很高.和dezhou聊过之后我仔细考虑了一下, ...

  6. spring学习总结一----控制反转与依赖注入

    spring作为java EE中使用最为广泛的框架,它的设计体现了很多设计模式中经典的原则和思想,所以,该框架的各种实现方法非常值得我们去研究,下面先对spring中最为重要的思想之一----控制反转 ...

  7. 简单了解Spring的控制反转和依赖注入

    浅谈控制反转(Inversion of Control,IOC) 我们首先先来了解一下控制二字,也就是在控制"正"转的情况下,在任何一个有请求作用的系统当中,至少需要有两个类互相配 ...

  8. spring的容器(控制反转、依赖注入)

    一.spring的容器 ”容器“是spring的一个重要概念,其主要作用是完成创建成员变量,并完成装配. 而容器的特点”控制反转“和”依赖注入“是两个相辅相成的概念. 控制反转:我们在使用一个类型的实 ...

  9. spring(3)------控制反转(IOC)/依赖注入(DI)

    一.spring核心概念理解 控制反转: 控制反转即IoC (Inversion of Control).它把传统上由程序代码直接操控的对象的调用权交给容器.通过容器来实现对象组件的装配和管理. 所谓 ...

  10. 【Spring Framework】Spring 入门教程(一)控制反转和依赖注入

    参考资料 Spring 教程 说在前面 什么样的架构,我们认为是一个优秀的架构? 判断准则:可维护性好,可扩展性好,性能. 什么叫可扩展性好? 答:在不断添加新的代码的同时,可以不修改原有代码,即符合 ...

随机推荐

  1. PyQt(Python+Qt)学习随笔:exit code 1073741845与槽函数所在对象不能定义同名实例方法问题

    最近做了几次测试,在PyQt中如果使用与槽函数同名的实例方法可能会导致不可控的错误. 案例1:如果两个信号映射到同名的槽函数,虽然参数不一样,但真正响应的槽函数是最后定义的槽函数,具体案例请见< ...

  2. centos7 yum搭建lamp

    环境 系统:centos7 安装apache #yum 安装apache [root@localhost ~]# yum install httpd httpd-devel #启动httpd服务 [r ...

  3. 5分钟入门MP4文件格式

    写在前面 本文主要内容包括,什么是MP4.MP4文件的基本结构.Box的基本结构.常见且重要的box介绍.普通MP4与fMP4的区别.如何通过代码解析MP4文件 等. 写作背景:最近经常回答团队小伙伴 ...

  4. 【面试题】GC Root都有哪些?

    那天去面试,面试官问我JVM垃圾回收,我是有备而来,上来就是一个可达性分析算法,然后就是一个复制算法,标记-清理,标记-整理,以及几个常见的垃圾回收器 详情见:https://www.cnblogs. ...

  5. Norns.Urd 中的一些设计

    Norns.Urd 是什么? Norns.Urd 是一个基于emit实现动态代理的轻量级AOP框架. 版本基于 netstandard2.0. 所以哪些.net 版本能用你懂的. 完成这个框架的目的主 ...

  6. C# 9.0新特性详解系列之五:记录(record)和with表达式

    1 背景与动机 传统面向对象编程的核心思想是一个对象有着唯一标识,表现为对象引用,封装着随时可变的属性状态,如果你改变了一个属性的状态,这个对象还是原来那个对象,就是对象引用没有因为状态的改变而改变, ...

  7. Vue-组件化,父组件传子组件常见传值方式

    前言 我们都知道vue核心之一:组件化,vue中万物皆组件,组件化我认为应该来至于模块化的设计思想,比如在模块化开发中,一个模块就是一个实现特定功能的独立的文件,有了模块我们就更方便去阅读代码,更方便 ...

  8. emca配置EM

    EM DC(Enterprise Manager Database Control)是 web 界面的数据库管理工具, 可用于配置 EM DC环境的工具包括: Oracle Universal In ...

  9. JavaSE19-IO特殊流和Properties集合

    1.IO特殊操作流 1.1 标准输入流 System类中有两个静态的成员变量 public static final InputStream in:标准输入流.通常该流对应于键盘输入或由主机环境或用户 ...

  10. 升级jenkins之后无法启动 报错Unable to read /var/lib/jenkins/config.xml

    故障记录 点击jenkins升级后再点击回滚到之前版本,jenkins就起不来了. 欲哭无泪,报错如下 hudson.util.HudsonFailedToLoad: org.jvnet.hudson ...