无论是用COM的方式,还是普通DLL,抑或.NET方式来实现插件框架,首先要面临的问题就是如何订立契约。如同我上一篇文章讲到的一样,契约是应用程序和插件之间进行交互的依据和凭证。应用程序必须声明我有什么样的功能可被插件使用,并且插件必须符合什么条件才能被我使用。反之,插件必须要知道应用程序提供什么样的功能,我才能将自己的功能融入到应用程序的体系中。本系列文章主要讲如何使用.NET实现插件式的应用程序框架,所以其它的方式我就不再提了。
如何使用.NET订立契约呢?首先想到的Interface,其次是抽象类,但是在插件模式中我使用接口,因为我们是在满足应用程序的主要目的的基础上来提供附加的插件功能,就这一点来说,接口更灵活,更容易扩展。接下来,如何订立契约的内容呢?这就要根据你的业务需求了,为了讲解的方便,我们定义一个最最基本的插件式应用程序的插件契约。我们做一个假定,我们的应用程序是一个多文档的应用程序,包含一个主菜单栏,一个工具栏,菜单栏可以在程序的上下左右四个方向停靠,另外还有一个状态栏。到后边,如果有必要,我会扩展这个应用程序,让他本身提供更多的可供插件使用的功能。所以就目前而言,我想实现的功能就是让插件为主程序添加工具条,菜单项并实现一些简单的功能。
应用程序向插件提供服务有两种方式,一种是直接再应用程序接口中声明属性或者方法,一种是将应用程序接口声明成一个服务容器。我打算两种方式都用,明确的功能就在接口中直接声明成属性或者方法,另外将应用程序声明成一个服务容器,以方便插入更多的服务功能,提高应用程序的可扩展性。
下边是一个非常简单的应用程序接口定义,对于我们的假定已经足够了。
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![ExpandedSubBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![ExpandedBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
插件的接口定义:
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![ExpandedBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)