前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻。如果没有看过前面的文章,请到我的博客首页查看。
前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要采用分层架构,就拿最简单的三层架构来说吧,我们通常把业务逻辑写在DLL中,现在就来写一个例子,看看如何在不编译整个项目的情况下,轻松的实现扩展。先透露一下,我们只要添加一个DLL就可以了。
这里就以银行为例子吧,首先新建一个控制台项目,还叫MEFDemo吧,然后建一个类库写接口,然后再建一个类库实现接口。项目结构如下:
MEFDemo和BankOfChina都只引用接口项目,MEFDemo不需要引用BankOfChina。
BankInterface的代码如下,做个简单实例,写几个方法测试一下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace BankInterface { public interface ICard { //账户金额 double Money { get; set; } //获取账户信息 string GetCountInfo(); //存钱 void SaveMoney(double money); //取钱 void CheckOutMoney(double money); } }
这里添加一个中国银行卡,实现接口,引用命名空间什么的不再重复说了,不懂看前面的文章,代码如下:
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; } } }
然后编写主程序,代码如下:
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 { [ImportMany(typeof(ICard))] public IEnumerablecards { get; set; } static void Main(string[] args) { Program pro = new Program(); pro.Compose();
foreach (var c in pro.cards)
{
Console.WriteLine(c.GetCountInfo());
}
Console.Read(); } private void Compose() { var catalog = new DirectoryCatalog("Cards"); var container = new CompositionContainer(catalog); container.ComposeParts(this); } } }
现在,我们知道只有一种银行卡,及中国银行的,注意我标红的代码,这里是一个目录,及主程序所在目录的Cards文件夹,我们把生成的BankOfChian.dll拷贝到这个文件夹下,然后运行才可以正确输出信息(毕竟我们没有引用那个项目),如图:
到了这里相信大家已经明白了,如果现在需求改变了,需要支持建行、农行等银行卡,怎么办呢?通常我们要改项目,把整个项目都编译再重新发布。但是现在不需要这么做了,我们只需要添加一个类库项目,把生成的dll拷贝到Cards目录下即可。
我们在这个解决方案下继续添加一个类库项目,实现ICard接口,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel.Composition; using BankInterface; namespace NongHang { [Export(typeof(ICard))] public class NHCard : ICard { public string GetCountInfo() { return "Nong Ye Yin Hang"; } public void SaveMoney(double money) { this.Money += money; } public void CheckOutMoney(double money) { this.Money -= money; } public double Money { get; set; } } }
点击右键编译,把生成的dll拷贝到Cards目录下面,运行看到如下结果:
再看看Cards目录中,现在你添加几个dll,就会显示多少条信息了。
源码下载
MEF系列文章:
C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo
C#可扩展编程之MEF学习笔记(二):MEF的导出(Export)和导入(Import)
C#可扩展编程之MEF学习笔记(三):导出类的方法和属性
C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
C#可扩展编程之MEF学习笔记(五):MEF高级进阶