论文部分内容阅读
摘 要:利用插件技术,人们可以随时扩展宿主程序的功能,这不仅提高了程序的扩展性,也降低了宿主程序域各插件功能上的耦合,使程序变得更加容易维护。
关键词:NET Framework;MEF;插件;解耦
1 MEF介绍
Managed Extensibility Framework(MEF)是.NET平台下的一个扩展性管理框架,它是一系列特性的集合,包括依赖注入等。MEF为开发人员提供了一个工具,让我们可以轻松地对应用程序进行扩展并且对已有的代码产生最小的影响。在开发过程中,研发人员可以根据业务需求定义一些扩展点,在后期的维护中便可使用这些扩展点与应用程序交互;同时MEF使得宿主程序与扩展程序之间不产生直接的依赖,这样做的好处之一是多个具有同样的扩展需求之间可以很容易共享扩展程序。
1.1 MEF体系结构
MEF通过部件和容器来构建。容器在类别中查找部件,类别在程序集或目录中查找部件。容器把入口连接到出口上,部件因此可以用于宿主应用程序。
MEF的核心技术是组合部件,它由一系列特性来描述和创建。每一个部件通过附加Export特性向其他部件提供功能,并通过附加Import特性来引用其他部件的功能。创建一个部件后,通过在定义好的部件目录中查找需要的功能来实现部件的组装。
MEF包括3大类别:用于宿主的类、基元类和基于特性机制的类。宿主类包含类别和容器。基元类可以用作基类,来扩展MEF体系结构,以使用其他技术连接出口和入口。通过反射构成基于特性机制的实现方式的类,如Export和Import特性等,提供扩展方法,便于使用的基于特性的部件的类,这些也是MEF的一部分。
1.2 MEF部件的构建过程
通过以下步骤便可轻松构建MEF程序:
(1)定义部件目录
(2)创建部件容器
(3)创建部件
(4)部件组装与实例化
1.3 声明一个部件
导出是部件向容器中的其他部件提供的一个值,而“导入”是部件向要通过可用导出满足的容器提出的要求。在特性化编程模型中,导入和导出是由修饰类或成员使用Import和Export特性声明的。Export特性可修饰类、字段、属性或方法,而Import特性可修饰字段、属性或构造函数参数。为了使导入与导出匹配,导入和导出必须具有相同的协定。
1.4 部件的生命周期
由于部件承载于组合容器中,因此其生命周期可能比普通对象更复杂。需要在关闭时执行工作的部件和需要释放资源的部件应照常为NET Framework对象实现IDisposable。但是,由于容器创建并维护对部件的引用,因此只有拥有部件的容器才应对其调用Dispose方法。容器本身实现IDisposable,并且作为Dispose中其清理的一部分,它将对拥有的所有部件调用Dispose。因此,当不再需要组合容器及其拥有的任何部件时,您应始终释放该组合容器。
2 利用MEF技术解耦程序
下文通过开发简单的数据库入库工具来逐步说明。
2.1 简单的入库工具
假设需要开发一款数据库入库工具,并且准备采用SQL Server作为数据库管理系统,可以使用在.NET下ADO.NET 进行数据库访问。
如果使用一段时间后,需要兼容其他的数据库,如Oracle、MySql等,这就可能需要修改代码,以适应新的需求。
很显然,访问数据库的业务逻辑与主程序产生了紧耦合,使得程序在需求改变后很难扩展,这不符合OCP(Open-Closed Principle)原则。
2.2 利用MEF技术实现解耦
上述问题如果使用MEF技术则很容易解决。将入库工具看作宿主程序,将入库的具体业务放入插件中执行。通过添加插件来实现兼容不同的数据库。
2.2.1 定义Import类型
在宿主程序中添加类型为IDataAccess的属性,并将Import特性附加其上。这样在程序运行中,部件在目录中查找接口协定,并实例化。而部件的组装是通过反射技术动态进行的,这样便可在任何时候在满足接口协定的情况下根据需要来实现IDataAccess。
应当将IDataAccess放在独立的程序集中,这样宿主程序集和插件程序集可以分别引用IDataAccess所在的程序集,从而避免了宿主程序集直接应用插件程序集而产生不必要的耦合。
2.2.2 定义Ecport
在实现IDataAccess的类中,需要加入Export特性,这是插件实现个关键步骤。因为部件在组装过程中根据Export特性来匹配和实例化。
MEF时基于反射来实现的。这样在后期需要兼容其他数据库时,只要新建独立的程序集并使用需要的数据库访问类实现IDataAccess接口,将上述程序集拷贝到宿主程序的运行目录中即可。
2.2.3 部件组装
部件组装很容易实现,只需定义部件目录DirectoryCatalog,并使用上述对象实例化部件容器CompositionContainer,同时使用部件容器的ComposeParts()方法,从特性化对象中创建可组合部件,并在当前容器中组合这些部件。只需3行代码便可完成部件的组装,具体如下:
var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
3 总结
MEF的组合基元是可扩展支持的本质,它看起来显得非常的简单,但却有能够支持强大的功能并且不失灵活性。上例中正是利用这种原理轻松的实现了主程序与具体的业务之间的解耦。
参考文献
[1]ChristianNagel ProfessionalC#4and. NET4[M].清华大学出版社,2010.
(作者单位:安徽四创电子股份有限公司)
关键词:NET Framework;MEF;插件;解耦
1 MEF介绍
Managed Extensibility Framework(MEF)是.NET平台下的一个扩展性管理框架,它是一系列特性的集合,包括依赖注入等。MEF为开发人员提供了一个工具,让我们可以轻松地对应用程序进行扩展并且对已有的代码产生最小的影响。在开发过程中,研发人员可以根据业务需求定义一些扩展点,在后期的维护中便可使用这些扩展点与应用程序交互;同时MEF使得宿主程序与扩展程序之间不产生直接的依赖,这样做的好处之一是多个具有同样的扩展需求之间可以很容易共享扩展程序。
1.1 MEF体系结构
MEF通过部件和容器来构建。容器在类别中查找部件,类别在程序集或目录中查找部件。容器把入口连接到出口上,部件因此可以用于宿主应用程序。
MEF的核心技术是组合部件,它由一系列特性来描述和创建。每一个部件通过附加Export特性向其他部件提供功能,并通过附加Import特性来引用其他部件的功能。创建一个部件后,通过在定义好的部件目录中查找需要的功能来实现部件的组装。
MEF包括3大类别:用于宿主的类、基元类和基于特性机制的类。宿主类包含类别和容器。基元类可以用作基类,来扩展MEF体系结构,以使用其他技术连接出口和入口。通过反射构成基于特性机制的实现方式的类,如Export和Import特性等,提供扩展方法,便于使用的基于特性的部件的类,这些也是MEF的一部分。
1.2 MEF部件的构建过程
通过以下步骤便可轻松构建MEF程序:
(1)定义部件目录
(2)创建部件容器
(3)创建部件
(4)部件组装与实例化
1.3 声明一个部件
导出是部件向容器中的其他部件提供的一个值,而“导入”是部件向要通过可用导出满足的容器提出的要求。在特性化编程模型中,导入和导出是由修饰类或成员使用Import和Export特性声明的。Export特性可修饰类、字段、属性或方法,而Import特性可修饰字段、属性或构造函数参数。为了使导入与导出匹配,导入和导出必须具有相同的协定。
1.4 部件的生命周期
由于部件承载于组合容器中,因此其生命周期可能比普通对象更复杂。需要在关闭时执行工作的部件和需要释放资源的部件应照常为NET Framework对象实现IDisposable。但是,由于容器创建并维护对部件的引用,因此只有拥有部件的容器才应对其调用Dispose方法。容器本身实现IDisposable,并且作为Dispose中其清理的一部分,它将对拥有的所有部件调用Dispose。因此,当不再需要组合容器及其拥有的任何部件时,您应始终释放该组合容器。
2 利用MEF技术解耦程序
下文通过开发简单的数据库入库工具来逐步说明。
2.1 简单的入库工具
假设需要开发一款数据库入库工具,并且准备采用SQL Server作为数据库管理系统,可以使用在.NET下ADO.NET 进行数据库访问。
如果使用一段时间后,需要兼容其他的数据库,如Oracle、MySql等,这就可能需要修改代码,以适应新的需求。
很显然,访问数据库的业务逻辑与主程序产生了紧耦合,使得程序在需求改变后很难扩展,这不符合OCP(Open-Closed Principle)原则。
2.2 利用MEF技术实现解耦
上述问题如果使用MEF技术则很容易解决。将入库工具看作宿主程序,将入库的具体业务放入插件中执行。通过添加插件来实现兼容不同的数据库。
2.2.1 定义Import类型
在宿主程序中添加类型为IDataAccess的属性,并将Import特性附加其上。这样在程序运行中,部件在目录中查找接口协定,并实例化。而部件的组装是通过反射技术动态进行的,这样便可在任何时候在满足接口协定的情况下根据需要来实现IDataAccess。
应当将IDataAccess放在独立的程序集中,这样宿主程序集和插件程序集可以分别引用IDataAccess所在的程序集,从而避免了宿主程序集直接应用插件程序集而产生不必要的耦合。
2.2.2 定义Ecport
在实现IDataAccess的类中,需要加入Export特性,这是插件实现个关键步骤。因为部件在组装过程中根据Export特性来匹配和实例化。
MEF时基于反射来实现的。这样在后期需要兼容其他数据库时,只要新建独立的程序集并使用需要的数据库访问类实现IDataAccess接口,将上述程序集拷贝到宿主程序的运行目录中即可。
2.2.3 部件组装
部件组装很容易实现,只需定义部件目录DirectoryCatalog,并使用上述对象实例化部件容器CompositionContainer,同时使用部件容器的ComposeParts()方法,从特性化对象中创建可组合部件,并在当前容器中组合这些部件。只需3行代码便可完成部件的组装,具体如下:
var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
3 总结
MEF的组合基元是可扩展支持的本质,它看起来显得非常的简单,但却有能够支持强大的功能并且不失灵活性。上例中正是利用这种原理轻松的实现了主程序与具体的业务之间的解耦。
参考文献
[1]ChristianNagel ProfessionalC#4and. NET4[M].清华大学出版社,2010.
(作者单位:安徽四创电子股份有限公司)