.NET框架之---MEF托管可扩展框架
2017-10-18 19:02
302 查看
MEF简介:
今天学习了下MEF框架,MEF,全称Managed Extensibility Framework(托管可扩展框架)。MEF是专门致力于解决扩展性问题的框架,MSDN中对MEF有这样一段说明:
Managed Extensibility Framework 或 MEF 是一个用于创建可扩展的轻型应用程序的库。 应用程序开发人员可利用该库发现并使用扩展,而无需进行配置。 扩展开发人员还可以利用该库轻松地封装代码,避免生成脆弱的硬依赖项。 通过 MEF,不仅可以在应用程序内重用扩展,还可以在应用程序之间重用扩展。
我们通过例子1来看下MEF是如何工作的:
例子1:
新建个WPF程序--MEFtestpro,添加引用System.ComponentModel.Composition,MEF的核心就是在此类库中实现的
项目结构图:
添加一个接口IApple.cs
然后添加三个类RedApple.cs
最后,主程序MainWindow.xaml.cs
然后运行看结果,如下:
可以看到,我们没有实例化类,而是仅仅通过Export和Import一个中间类型(IApple),就实现了调用类中的方法!
这就实现了主程序和类之间的解耦,大大提高了代码的扩展性和易维护性!
可能有人就会说多此一举,既然我们可以实例化类,为什么非要用这种奇怪的语法。
其实如果我们站在软件框架设计的层面,它的好处就是可以减少dll之间的引用,使你的程序更加健壮可扩展
接下来请看例子2.
例子2:
新建控制台程序MEFtestPro2
项目结构图:
新增.NET类库Fruit,里面包含了一个接口IFruit
新增.NET类库Banana,引用Fruit.DLL
新增.NET类库Orange,引用Fruit.DLL
最后主程序program.cs,引用Fruit.DLL
现在,我们把生成的Banana.dll和Orange.dll拷贝到这个文件夹下,如图:
然后运行才可以正确输出信息(毕竟我们没有引用那个项目),如图:
注意,我们仅仅是把Banana.dll和Orange.dll拷贝到我们指定的目录,然后通过MEF导入导出中间类型(IFruit),
实现了主程序调用未知的DLL中的方法,而主程序并未引用该DLL
总结一下MEF框架的好处:
1.解耦。试想下,如果主程序引用了Banana.dll和Orange.dll,那么就意味着你可以无限制的开放DLL中类,属性,方法的访问权限,也就意味着主程序中会出现很多耦合的代码,哪天你想移除这个DLL,程序肯定编译失败,而且你要手动删除这些耦合代码,而MEF因为是通过中间接口来完成调用的,所以只向外暴露了接口里面的成员,程序员是无法任意调用DLL中的任何方法,只能通过接口来调用。就算删掉这个DLL,程序也能正常运行!
2.可扩展性。举个例子,假设你的程序已经移交给客户了,哪天客户说我不想看Banana了,我想换一个水果,苹果Apple,这时,你只需重写一个Apple.DLL,使其继承并实现IFruit接口,然后,只要将Apple.dll交给客户,并让其覆盖Banana.DLL,打开程序,你会发现香蕉变成了苹果。是不是很方便!如果是以前,你可能得重新将所有有关banana的东西全部替换,然后重新编译,发布,再将整个程序移交客户,这样说大家应该都明白了!
3.MEF不仅可以导出类,还可以导出方法,属性,不管是私有还是公有,从而满足更多的需求!
最后,有人需要上述的源程序例子,可点击链接下载:http://download.csdn.net/download/wcc27857285/10030752
参考资料:http://www.cnblogs.com/yk123/p/5350133.html
未完待续。。。。。
今天学习了下MEF框架,MEF,全称Managed Extensibility Framework(托管可扩展框架)。MEF是专门致力于解决扩展性问题的框架,MSDN中对MEF有这样一段说明:
Managed Extensibility Framework 或 MEF 是一个用于创建可扩展的轻型应用程序的库。 应用程序开发人员可利用该库发现并使用扩展,而无需进行配置。 扩展开发人员还可以利用该库轻松地封装代码,避免生成脆弱的硬依赖项。 通过 MEF,不仅可以在应用程序内重用扩展,还可以在应用程序之间重用扩展。
我们通过例子1来看下MEF是如何工作的:
例子1:
新建个WPF程序--MEFtestpro,添加引用System.ComponentModel.Composition,MEF的核心就是在此类库中实现的
项目结构图:
添加一个接口IApple.cs
namespace MEFtestpro { public interface IApple { string GetAppleColor(); } }
然后添加三个类RedApple.cs
namespace MEFtestpro { [Export ("Apple",typeof(IApple))] //将RedApple类导出类型为IApple接口 class RedApple : IApple { public string GetAppleColor() { return "Red"; } } [Export("Apple", typeof(IApple))] //将GreedApple类导出类型为IApple接口 class GreedApple : IApple { public string GetAppleColor() { return "Green"; } } [Export("Apple", typeof(IApple))] //将YellowApple类导出类型为IApple接口 class YellowApple : IApple { public string GetAppleColor() { return "Yellow"; } } }
最后,主程序MainWindow.xaml.cs
namespace MEFtestpro { public partial class MainWindow : Window { [ImportMany("Apple")] //Apple是契约名字,可以任意起,但是要注意别重名 public IEnumerable<IApple> Apples { get; set; } public MainWindow() { InitializeComponent(); this.Compose(); if (this.Apples != null) { string s=string.Empty; foreach (var apple in Apples) //将内容显示在label上 { s=s+ apple.GetAppleColor()+"\r\n"; label.Content = s; } } } //这个方法表示添加当前Program这个类到组合容器,为什么要添加到组合容器? //是因为只要添加到组合容器中之后,如果该类里面有Import,MEF才会自动去寻找对应的Export。 //这也就是为什么使用MEF前必须要组合部件的原因。 private void Compose() { var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); CompositionContainer container = new CompositionContainer(catalog); container.ComposeParts(this); } } }
然后运行看结果,如下:
可以看到,我们没有实例化类,而是仅仅通过Export和Import一个中间类型(IApple),就实现了调用类中的方法!
这就实现了主程序和类之间的解耦,大大提高了代码的扩展性和易维护性!
可能有人就会说多此一举,既然我们可以实例化类,为什么非要用这种奇怪的语法。
其实如果我们站在软件框架设计的层面,它的好处就是可以减少dll之间的引用,使你的程序更加健壮可扩展
接下来请看例子2.
例子2:
新建控制台程序MEFtestPro2
项目结构图:
新增.NET类库Fruit,里面包含了一个接口IFruit
namespace Fruit { public interface IFruit { string GetFruitName(); } }
新增.NET类库Banana,引用Fruit.DLL
namespace Banana { [Export(typeof(IFruit))] public class Banana : IFruit { public string GetFruitName() { return "Banana"; } } }
新增.NET类库Orange,引用Fruit.DLL
namespace Orange { [Export(typeof(IFruit))] public class Orange : IFruit { public string GetFruitName() { return "Orange"; } } }
最后主程序program.cs,引用Fruit.DLL
namespace MEFtestPro2 { class Program { [ImportMany(typeof(IFruit))] public IEnumerable<IFruit> fruits { get; set; } static void Main(string[] args) { Program pro = new Program(); pro.Compose(); foreach (var f in pro.fruits) //打印输出 { Console.WriteLine(f.GetFruitName()); } Console.Read(); } private void Compose() { var catalog = new DirectoryCatalog("fruits"); //fruits是一个目录名称,就是主程序所在目录(bin-Debug-fruits)文件夹(我们需要提前建立好) var container = new CompositionContainer(catalog); container.ComposeParts(this); } } }
现在,我们把生成的Banana.dll和Orange.dll拷贝到这个文件夹下,如图:
然后运行才可以正确输出信息(毕竟我们没有引用那个项目),如图:
注意,我们仅仅是把Banana.dll和Orange.dll拷贝到我们指定的目录,然后通过MEF导入导出中间类型(IFruit),
实现了主程序调用未知的DLL中的方法,而主程序并未引用该DLL
总结一下MEF框架的好处:
1.解耦。试想下,如果主程序引用了Banana.dll和Orange.dll,那么就意味着你可以无限制的开放DLL中类,属性,方法的访问权限,也就意味着主程序中会出现很多耦合的代码,哪天你想移除这个DLL,程序肯定编译失败,而且你要手动删除这些耦合代码,而MEF因为是通过中间接口来完成调用的,所以只向外暴露了接口里面的成员,程序员是无法任意调用DLL中的任何方法,只能通过接口来调用。就算删掉这个DLL,程序也能正常运行!
2.可扩展性。举个例子,假设你的程序已经移交给客户了,哪天客户说我不想看Banana了,我想换一个水果,苹果Apple,这时,你只需重写一个Apple.DLL,使其继承并实现IFruit接口,然后,只要将Apple.dll交给客户,并让其覆盖Banana.DLL,打开程序,你会发现香蕉变成了苹果。是不是很方便!如果是以前,你可能得重新将所有有关banana的东西全部替换,然后重新编译,发布,再将整个程序移交客户,这样说大家应该都明白了!
3.MEF不仅可以导出类,还可以导出方法,属性,不管是私有还是公有,从而满足更多的需求!
最后,有人需要上述的源程序例子,可点击链接下载:http://download.csdn.net/download/wcc27857285/10030752
参考资料:http://www.cnblogs.com/yk123/p/5350133.html
未完待续。。。。。
相关文章推荐
- 托管可扩展框架MEF高清视频下载+在线Silverlight流式播放+源代码+PPT
- Managed Extensibility Framework(MEF) 自动发现式扩展框架
- 【设计】【托管扩展性框架】 MEF vs 2010 samples
- MEF-托管可扩展架构
- MEF(Managed Extensibility Framework ) 可控扩展框架
- Dbunit(基于junit扩展的数据库测试框架。)vs Jmockit
- YII2框架学习 扩展篇(二) 事件机制
- 使用express.js框架一步步实现基本应用以及构建可扩展的web应用
- ASP.NET中把扩展名.aspx改成自定义的扩展名.mspx,如何在IIS与.net框架中配置
- 扩展Excel Services编程框架(翻译MSDN文章)
- 可扩展的开源移动端框架:Helios
- C# MEF 通用插件框架
- 建立可扩展的silverlight 应用框架 step-3
- [置顶] GitHub 版本控制 项目托管 00 总体框架
- 建立可扩展的silverlight 应用框架 step-5
- PHP的Yii框架中YiiBase入口类的扩展写法示例
- 建立可扩展的silverlight 应用框架 step-6
- MEF框架学习之旅(六)元数据和元数据视图
- 用Spring提供的JUnit框架扩展对DAO或Service层进行单元测试
- ThinkPHP框架设计与扩展总结