This project is read-only.

1. 首先,您想问?

1.1. 它是什么类型的插件框架?

作为有经验的电脑用户和软件工程师,您已经见识过各种各样的插件框架了。 比如暴风影音的解码器、Photoshop的滤镜、Vim的语法高亮、Visual Studio、Eclipse、Sharpdevelop……它们都用到了插件框架,并且给用户带来了很大的方便。按照其能够达到的目标,我们可以将其归为如下三类:

  1. 使软件某方面的功能能够被灵活地扩展,如暴风影音的解码器、Photoshop的滤镜、gVim的语法高亮。
  2. 允许用户通过编写符合其规范的插件对系统功能进行扩展并且提供了一定程度定制能力,如Visual Studio。
  3. 整个系统由一些插件和一个插件宿主组成从而提供了更加灵活的定制能力和可扩充性,如Sharpdevelop,Eclipse。

 

虽然您会说,他们的优点显而易见并且满足了各自的应用情形;但是我们不得不承认它们都有不同层次的不足。第一种插件形式的缺点是很明显的,它仅能提供很有限的扩充能力,事实上它还算不上框架。对于纯粹的用户来说,第二种和第三种插件框架之间几乎没有什么区别。当查看了它们的源码或者编写了一个对其进行扩展的插件后,其中的区别就能够被察觉出来。那就是:

第二种插件框架的宿主完成了太多的功能以至于其提供的基础服务使得系统的扩展能力受到限制,比如Visual Studio提供了一个应用程序对象用来取得当前文档、活动窗体、各种界面对象等用以插件和宿主之间的交互。对于这种形式的插件框架,由于宿主已经规定了系统的目的(比如Visual Studio就是一个IDE)插件之间几乎不需要交互。 而对于第三种框架甚至为系统提供交互界面的部分都可以作为一个插件提供。但是好像很遗憾,SharpDevelop,Eclipse都没有将界面部分作为一个插件来提供。 虽然有不少其它类Eclipse插件框架(OSGI)的实现将界面部分抽离为一个插件,但是这个插件很难被替换掉从而难以使系统轻松具有不同风格的界面。 SharpDevelop的插件形式多被实现为第二种插件框架,虽然SharpDevelop本身是全插件形式也有不少模仿SharpDevelop的其它全插件形式的实现,但都没有考虑将界面部分作为一个插件提供。

本插件框架成功地避免了以上各种现存插件框架的不足。首先,对宿主进行了最大程度的瘦身,宿主仅负责插件和服务的装载和卸载以及系统启动的流程控制。第二,为系统运行提供界面的部分也作为插件提供并且能够轻松替换。整个系统通过两个配置文件装配起来,一个是注册到系统中的插件列表,另一个是界面说明文件。此外,本插件框架还提供了灵活的插件间交互方式。

1.2. 为什么我会需要这样一个插件框架?

作为公司或者部门的技术主管,您肯定在不断寻求提高生产力的手段和技术。那么这就是一个不错的选择。本插件框架在快速开发WinForm应用程序和C/S系统时有非凡的表现(其实应该说是装配,因为如果使用这个插件框架相同的功能只需开发一次)。 每一个有经验的软件工程师都会承认,在很多情况下我们的小组或者部门甚至我们的公司都会专注于软件的某一应用领域。 此时客户的需求有很大的重叠度,为了避免重复的工作,我们会寻求各种办法来提高重用性,以期减少重复的工作增加生产力。

您肯定已经采用了各种层次的重用性手段。从代码片段到代码集合的源代码级别的重用,从可重用小构件到较大的模块的动态链接技术层次的重用。 有了这样一套插件框架您就可以将重用级别再向前推进一步,面向客户需求的重用。事实上,绝大数插件框架都是面向客户需求的重用,只不过实现程度不一样而已。 只要使用的是在上一节提到的第三种插件机制,就可以重用以前开发的插件快速构建一个原型系统。然后对不满足用户需求的插件进行微调,新增的需求通过编写新的插件来满足。 然而,此插件框架的优势并不止于此,其创建插件宿主程序的简易程度绝对能够让你惊愕。

首先在IDE中新建一个WinForm应用程序项目,删除IDE生成的除Program.cs之外的代码文件。然后添加对AddIn.Core.dll的引用。再修改Main方法为:

  	static void Main(string[] args)
  	{
  		AppFrame app = new AppFrame();
  		app.Run();
  	} 

然后修改宿主程序的图标编译即可。

本插件框架还有另外一个显著的优势——提供系统交互界面的部分作为一个插件提供并且能够很容易地被替换掉。 有些时候我们和竞标对手的软件在功能和易用性上势均力敌,如果我们的软件有一个漂亮的交互界面肯定能大大增加夺标的概率。有时候我们的用户更加崇尚简洁,有时候我们的用户不愿意为更加华丽的界面付账,此时我们可以对基本的WinForm控件加以扩展使用。本人开发了一个免费开源的WinForm扩展控件集合,它不排斥商业使用。使用此开源控件集再配合另外几个开源控件足以开发出专业程度媲美Visual Sutudio 2005的交互界面。

2. 更进一步的信息

2.1. 它能够运行在那些平台上?

这可能是最容易回答的问题,也可能是最不容易回答的问题。它的核心部分纯粹使用C#语言开发,可以运行于.NET 2.0及以上的平台上,也可以运行于其它实现了.NET 2.0及更高版本的操作系统上。

但是他到底能不能跨越操作系统这个平台,还需要根据具体情况来定。如果在这个系统中使用的所有插件都被实现为能够跨平台的那么装配出来的应用程序就是跨平台的。如果任何一个需要在这个系统使用的插件被实现成为平台相关的那么整个系统就是平台相关的。

2.2. 有那些成功的应用案例?

至此,您或许想知道这个插件框架在实际使用中能够有什么样的表现。所以您会问,有哪些成功的案例?通过应用案例来考技术的实用性是一个非常重要的手段。当然有基于这个插件框架的成功案例——Mini Internet Explorer,一个网页浏览器。

到目前为止,整个插件框架的开发只是我一个人的表演,所以不可能选择一个陌生的应用领域来开发应用案例。如果这样的话需求确认和系统开发都将成为一个巨大的任务,而真正需要做的就是测试插件框架在易用性、稳定性、界面分离程度、界面的专业化程度。我选择使用该插件框架开发一个网页浏览器来检测其实用性。网页浏览器是每一个使用电脑的人每一天都在用的软件以至于它的需求确认是如此的容易——我只需要问我自己需要它具有哪些功能。此外,浏览器具有丰富的图形界面。

  1. 浏览器的网址输入下拉框需要为浏览提供网址,想想如果所有提供给用户的功能只能通过点击按钮来调用将会是一种什么情况。
  2. 需要向浏览器的网址输入下拉框添加最近访问的网址,这代表了选项类界面元素中的选项可以在系统运行过程中发生改变。Visual Studio的查找、撤销就是实例。
  3. 浏览器的网址收藏工具条和菜单需要根据收藏夹的具体内容创建,这代表了界面元素能够在启动时根据具体情况被创建,而不是界面配置文件将界面描述为什么样就必须是什么样,改变不了了。这还为插件的插件提供了可能。
  4. 浏览器需要一个进度条来指示页面打开进度,需要通过前进、后退按钮的可用性来指明当前用户数据的状态、用户下一步可进行的操作。

 

完成了这些,首先就能够说明这套插件框架能够创建出专业化程度很高的应用系统。如果要完成这些浏览器插件和UI插件必须要有良好的交互,当然也就说明了本插件框架提供了优秀的插件间交换手段。 

2.3. 需要付钱吗?从哪里可以获得?

不需要,它是免费的。但是如果需要替换UI插件的话,您或许需要支付购买第三方界面组件的费用。如果您认为有必要让我为贵处封闭开发一套UI插件的话,您还需要支付劳务费用给我。但是我将会免费为您奉送重构了的插件框架;它的易用性、稳定性更高,UI插件的替换也更加容易。

2.4. 如何获得技术支持?

如果需要让我为您开发UI插件,请发邮件到tr0217@163.com

您可以发邮件到tr0217@163.com或者到我的博客上留言说明您遇到的问题。

3. 授权与责任声明

3.1. 授权

本插件的基础版本尚未采纳任何其它软件发布协议(目前采用The MIT License)。本人在在此声明:

  1. 基础版本完全免费,您可以获得任何使用自由。包括应用于商业项目和对此插件框架进行逆向工程。
  2. 如果您对本插件框架进行修正并且再发布,请明确指明您发布的版本与原始版本的区别。
  3. 如果您免费使用本插件框架,那么您有义务为改进此插件框架作出贡献。比如通过技术支持信息报告错误、分享您的扩展功能。
  4. 本人不保证不对后续版本进行加密处理。如果本人对后续版本进行加密处理,本人没有义务为您进行逆向工程创造便利。
  5. 本人不强制要求您需要在您的软件中明显声明您使用了本产品。但是如果您由于使用本产品的免费版本带来了问题而破坏我的名誉将是绝对不允许的。
  6. 本人不保证不会为本软件的后续版本采纳更为严格的授权协议。如果本人在后续版本中采纳了其它授权协议,那么您必须按照新采纳的授权协议使用本软件的后续版本。但是您也可以按照本授权声明使用本软件的当前版本。本软件的当前版本包括
    1. AddIn.Core.dll
    2. AddIn.Gui.dll
    3. AddIn.Config.exe
    4. WeifenLuo.WinFormsUI.Docking.dll 版本2.3.1.0 至 2.5.0.0都可以兼容
    5. log4net.dll 版本号:1.2.10.0
(这里的版本指的是文件版本。通常文件版本相同的不同程序集版本间都是兼容的)

 

3.2. 责任声明

由于基本版本准许免费使用,使用本插件框架带来的任何直接和间接问题本人概不负责。如果免费使用本插件框架,本人不保证技术支持的及时性。

如果您与我签订协议为贵方编写UI插件,那么本人也只能负限于插件框架核心部分和UI插件中由于本人实现所带来的有限责任。关于技术支持和其它责任及义务将会在协议中明确说明。

此外,可以看出本插件框架的基础版本使用了WeifenLuo.WinFormsUI.Docking.dlllog4net.dll。这是两款开源软件,他们使用的协议分别为The MIT LicenseApache License Version 2.0

这是两款非常友善的协议,都不排斥商业使用。

4. 关于插件框架的一般性问题

4.1. 插件框架的基本任务

设计全插件框架时有几个非常基本的问题需要考虑。

  1. 插件应该怎样被装载。插件需要被主程序装载然后调用。
  2. 是否需要实现界面模块和功能模块的分离,怎么实现。分离是为了让界面模块的更新不至于对功能模块的影响太大。
  3. 怎么实现界面和功能的连接。很多功能都是通过界面上的操作调用的,所以连接也是个基本的问题。

关于连接,我们所考虑的当然不能只是怎么将没有参数的方法通过点击界面上的一个按钮调用起来,还需要考虑一些复杂的情形以使装配出来的应用程序符合合理的界面设计原则。

4.2. 不得不考虑的界面设计原则

设计插件框架时同样必须考虑的界面设计原则有:

  1. 如果系统需要针对登入的用户限制一些功能,最好的做法是将调用当前用户不可执行功能的界面元素的Visible属性设为false。(这并不是必须的)
  2. 界面元素的Checked与Enabled的状态以及其它属性需要能够表示出用户当前的操作、当前用户数据所处的状态、用户下一步可进行的操作。在上面的网页浏览器中,组合框中显示了当前页面的网址。这就是界面元素的属性表示了用户当前的操作——用户正在浏览网址为http://tr0217.blog.163.com/的网页。状态栏中的进度条已经消失了,说明当前页面下载完成了:这就是界面元素表示了当前用户数据状态的例子。浏览栏、状态栏、收藏栏都是可见的,同时相应的菜单项的Checked属性都为true:这也可以认为是界面元素表示了当前用户数据的状态。在上图中在当前页面中打开新网址的界面元素处于可用状态,这是由于当前有页面打开:这就是界面元素表示了用户下一步可进行的操作。

     

  3. 界面不应该单调乏味,如界面上只有按钮和菜单。单调乏味的界面不仅影响美观,还会影响易用性。在这个浏览器的界面上如果只有按钮和菜单的话,输入网址应该怎么办呢?弹出一个对话框吗?这复杂了用户的操作,显然不符合界面设计的原则。

     

    如果提供丰富的界面,就会带来另外一些困难。某个界面元素调用的方法所需的参数需要另外一个界面元素提供。如上图所示,界面元素 调用的转到某个网址的方法的参数就需要它左边的组合框来提供。当然更多的情况是参数由调用者界面元素本身提供的,在组合框中输完网址后,按回车键也能够调用转到某个网址的方法。还有些情形下需要提供不变的参数。如上图中设置当前搜索引擎的两个菜单项,他们的参数就是固定的,从上到下分别是:“http://www.baidu.com/s?wd=,百度”、“http://www.google.com.hk/search?q=,谷歌”。比如使用百度搜索“Plugin”这个关键字时的调用URL为“http://www.baidu.com/s?wd=Plugin”。 “,”之后的文本则是这个搜索引擎的公认名称。

 

http://www.baidu.com/s?wd=,百度”其实表示了两个参数,“,”是一个分隔符。设置当前搜索引擎的方法的原型为Void SetSearchEngine(System.String, System.String),第一个参数表示搜索引擎的基本URL,第二参数表示搜索引擎的公认名称。这个参数用于更新状态栏中指示当前搜索引擎的文本框中显示的文字,如右图。(使用逗号作为参数分割符只是本插件框架的约定。)

4.3. 使用任何一款插件框架都需要注意的问题

为什么我们选择使用插件框架?

第一回答就是我们需要更大程度地重用。是的,使用插件框架能够将重用提升到满足客户需求的程度。我们编写的的一个又一个插件的目标在于满足客户的需求。可重用程度提高了生产力也就提高了。

插件框架带个我们的第二个好处就是可以灵活地定制、自由地扩展。我们可以删除以前开发的系统中不符合用户需求的插件,可以编写新的插件来满足用户不一样的需求。甚至用户也可以遵照插件框架的约定来对系统进行扩展。

明白我的暗示了吗?“遵照插件框架的约定”这就是限制。插件框架在带来这么多好处的同时也带来了限制。所以使用插件框架时我们需要冷静,插件框架并不能取代其它重用手段。我们不能因为有了插件框架就终止了我们在其它重用手段上的努力。有了插件框架我们仍然需要其它层次的可重用性——代码片段、源码库,小二进制组件、功能完善的组件。

这不是在哗众取宠。我已经见过了错误地使用插件框架的活生生的例子。由于他们在其它重用手段上停止了继续努力导致生产力不增反降。也或许他们从来没有评估过自己的生产力。

还有另外一个很重要的问题需要注意。插件框架的目标在于什么?通过重用以前开发的插件快速生产出满足客户需求的应用系统。所以注册到插件框架中的几乎所有插件都在于满足客户一个或者多个功能需求。所以在设计插件时就需要注意,插件的接口必须从满足用户的需求上进行考虑。其次才是提供有限的和其它插件交互的接口以满足交互和扩展需求。

通过上面的分析,我们得出了使用任何一款插件框架都需要注意的两个问题:

  1. 绝对不能放弃在其它复用手段上的努力。
  2. 设计插件时必须从满足用户需求上进行考虑。

 

4.4. 插件框架还需要完成那些任务

如果之前提到的三个基本任务都被完成了,那么插件框架已经具有很高的实用价值了。装配出的系统界面友好,能够很容易地更换界面组件使得系统的界面绚丽美观。此时还有其他的问题需要考虑。

每一款软件都不能说100%没有问题,当系统被部署后我们需要日志系统来诊断和定位问题。日志信息需要分不同的级别,可以输出到不同的目标(文件、控制台、数据库等)。

此外这是一个插件结构的系统,所有人都可以开发插件注册到其中。我们无法保证每一个插件都能够正确的被加载运行,所以必须要保证任何一个插件在加载和运行时出现的错误不会影响到系统的稳定性

有时在一个系统中将会有一些功能很少被使用,但是客户又有这样的需求。在这些插件加载后,它提供的功能却很少被使用,让这些插件在系统一启动就加载是很低效的做法。如果直到系统退出它的功能仍然没有被使用,那它占据的内存就白费了,加载它所消耗的时间也白费了。解决这个问题的办法就是延迟加载,意思是不在系统启动时加载它,当这个插件提供的功能第一次被使用时加载。

还有其它两个功能可以被提供。动态加载(热加载)——在系统运行中向系统中增加新的插件。动态卸载(热卸载)——在系统运行中卸载某个插件而不是等到系统退出时卸载。如果在系统运行中能够确定某个插件将不再使用就可以将其动态卸载。

5. 更加详细的文档

更加详细的文档包含在项目代码一起,在Doc目录下。

Last edited Feb 4, 2012 at 2:51 PM by TR0217, version 4

Comments

No comments yet.