关于.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 教程 说在前面 什么样的架构,我们认为是一个优秀的架构? 判断准则:可维护性好,可扩展性好,性能. 什么叫可扩展性好? 答:在不断添加新的代码的同时,可以不修改原有代码,即符合 ...
随机推荐
- 第14.15节 爬虫实战1:使用Python和selenium实现csdn博文点赞
写在前面:本文仅供参考学习,请勿用作它途,禁止转载! 在开始学爬虫时,学习了csdn博客专家(id:明天依旧可好 | 柯尊柏)<实战项目二:实现CSDN自动点赞>的文章,文章介绍了通过Py ...
- PyQt(Python+Qt)学习随笔:QAbstractItemView的alternatingRowColors属性
老猿Python博文目录 老猿Python博客地址 alternatingRowColors属性用于控制视图中不同行记录背景色是否使用交替不同的颜色. 如果此属性为True,则将使用QPalette. ...
- PyQt(Python+Qt)学习随笔:QAbstractItemView的SelectionBehavior属性
老猿Python博文目录 老猿Python博客地址 一.概述 SelectionBehavior属性用于控制选择行为操作的数据单位,是指选择时选中数据是按行.按列还是按项来选择.SelectionBe ...
- LeetCode初级算法之数组:48 旋转图像
旋转图像 题目地址:https://leetcode-cn.com/problems/rotate-image/ 给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: ...
- 区块链产业发展热潮来袭,Panda Global 认为体验、安全是关键词
作为一项近些年才发展起来的新型技术,区块链自诞生之日起就备受关注,凭着去中心化.不可篡改.信息透明等多种关键特点,已成为变革传统产业的一项有力创新手段.当区块链热潮再度袭来之时,知名数字货币交易所Pa ...
- IDEA将Java Web项目打war包
准备工作 1.IntelliJ IDEA开发工具 2.可以正常运行的Java Web项目 打war包流程 1.使用快捷键Ctrl+Alt+Shift+s 或者 鼠标点击选中项目名按F4 打开 Proj ...
- hive中的虚拟列
hive为用户提供了三个虚拟列:用户可以通过这三个虚拟列确定记录是来自哪个文件以及这条记录的具体位置信息 INPUT__FILE__NAME 返回记录所在的具体hdfs文件全路径 hive> s ...
- 用php简单区别泛解析
<?php header('content-type:text/html; charset=utf-8'); $host = '58.com'; $hosts = gethostbyname(' ...
- Python面向对象:封装和多态
一.封装 封装是隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读取和修改的访问级别. 封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进 ...
- python三大流程
一.三大流程 1. 顺序:按照顺序依次逐行执行代码的过程.自左向右,自上而下 2. 分支:程序按照不同的条件执行不同的处理代码的过程. 分支分为单分支,双分支,多分支 经常用到的分支结构是if语句 i ...