关于.NET中的控制反转(二)- 依赖注入之 MEF
一、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的更多相关文章
- 轻松了解Spring中的控制反转和依赖注入(二)
紧接上一篇文章<轻松了解Spring中的控制反转和依赖注入>讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作. 类 ...
- Spring中的控制反转和依赖注入
Spring中的控制反转和依赖注入 原文链接:https://www.cnblogs.com/xxzhuang/p/5948902.html 我们回顾一下计算机的发展史,从最初第一台计算机的占地面积达 ...
- 轻松了解Spring中的控制反转和依赖注入(一)
我们回顾一下计算机的发展史,从最初第一台计算机的占地面积达170平方米,重达30吨,到现如今的个人笔记本,事物更加轻量功能却更加丰富,这是事物发展过程中的一个趋势,在技术领域中同样也是如此,企业级Ja ...
- 在DoNetMVC中使用控制反转和依赖注入【DI】
本次是在MVC5中使用Autofac 第一步:程序包管理器控制台 Install-Package Autofac.MVC5 引入nuget包 这样成功之后,会在引用中出现两个DLL,分别是Autofa ...
- .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整-控制反转和依赖注入的使用
再次调整项目架构是因为和群友dezhou的一次聊天,我原来的想法是项目尽量做简单点别搞太复杂了,仅使用了DbContext的注入,其他的也没有写接口耦合度很高.和dezhou聊过之后我仔细考虑了一下, ...
- spring学习总结一----控制反转与依赖注入
spring作为java EE中使用最为广泛的框架,它的设计体现了很多设计模式中经典的原则和思想,所以,该框架的各种实现方法非常值得我们去研究,下面先对spring中最为重要的思想之一----控制反转 ...
- 简单了解Spring的控制反转和依赖注入
浅谈控制反转(Inversion of Control,IOC) 我们首先先来了解一下控制二字,也就是在控制"正"转的情况下,在任何一个有请求作用的系统当中,至少需要有两个类互相配 ...
- spring的容器(控制反转、依赖注入)
一.spring的容器 ”容器“是spring的一个重要概念,其主要作用是完成创建成员变量,并完成装配. 而容器的特点”控制反转“和”依赖注入“是两个相辅相成的概念. 控制反转:我们在使用一个类型的实 ...
- spring(3)------控制反转(IOC)/依赖注入(DI)
一.spring核心概念理解 控制反转: 控制反转即IoC (Inversion of Control).它把传统上由程序代码直接操控的对象的调用权交给容器.通过容器来实现对象组件的装配和管理. 所谓 ...
- 【Spring Framework】Spring 入门教程(一)控制反转和依赖注入
参考资料 Spring 教程 说在前面 什么样的架构,我们认为是一个优秀的架构? 判断准则:可维护性好,可扩展性好,性能. 什么叫可扩展性好? 答:在不断添加新的代码的同时,可以不修改原有代码,即符合 ...
随机推荐
- PLSQL Developer 工具应用
用户scott使用: 解锁scott: 第一步:登陆管理员 SQL语句:Sqlplus sys/tiger as sysdba 第二步:解锁scott SQL语句:Alter user scott a ...
- Scrum 冲刺 第一篇
Scrum 冲刺 第一篇 每个成员认领的任务 人员 任务 周立 后台登录注册模块 邓富荣 后台首页模块 钟俊豪 博客圈模块 黄清山 个人界面模块 郑焕 首页以及博客圈界面 黄梓浩 个人界面以及登录注册 ...
- CF850F Rainbow Balls 题解
考虑最后变成哪一种颜色. 设 \(s = \sum\limits_{i=1}^n a_i\) 设现在有 \(k\) 种当前颜色, 需要全部变成该种颜色, 期望步数为 \(f_k\). 考虑状态转移.设 ...
- MySQL技术内幕InnoDB存储引擎(一)——MySQL体系结构和存储引擎
1.数据库和实例 数据库(database)和实例(instance)不能混淆. 什么是数据库 数据库是物理操作系统文件或其他文件类型的集合.说白了,就是存储着的文件,不会运行起来,只能被实例增删改查 ...
- mac系统下用ssh方式连接git仓库
1.应用程序-终端,键入命令 ssh-keygen -t rsa -C "xxxxx@xxxxx.com" ,后面是你的邮箱地址.一直回车,生成密钥. 2.键入 open ~ ...
- 2. 使用Shell能做什么
批处理 在批处理的过程中,能够实现脚步自动化,比GUI自动化速度高效 日常工作场景 服务端测试 移动端测试 持续集成与自动化部署,这是最最场景的场景,可以说离开了shell,持续集成和自动化部署也会遇 ...
- Nginx(四):Keepalived+Nginx 高可用集群
Keepalived+Nginx 高可用集群 (主从模式) 集群架构图 安装keepalived [root@localhost ~]# yum install -y keepalived 查看状态 ...
- [日常摸鱼]bzoj1257余数之和
题意:输入$k,n$,求$\sum_{i=1}^n k \mod i$ $k \mod i=k-i*\lfloor \frac{k}{i} \rfloor $,$n$个$k$直接求和,后面那个东西像比 ...
- 图解 IP 基础知识!
我把自己以往的文章汇总成为了 Github ,欢迎各位大佬 star https://github.com/crisxuan/bestJavaer IP 协议 路由器对分组进行转发后,就会把数据包传到 ...
- Viterbi算法
clc;clear all;close all; Start_Pi = [-1,-1];State_k = ['H','L'];% 转移矩阵Transition_matrix = [-1,-1.322 ...