文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/

研一时,听当时的师兄推荐,买了蒋波涛的一本关于GIS插件框架的书。当时一边看书一边将其中的例子完整的实现了一遍,收益匪浅。后来由于项目需要,也做过一个插件的C/S系统,用的是微软提供的MEF框架。在这个系统中,把蒋波涛在他的书中没有涉及到的插件和插件的通信完成了。不过,蒋波涛的那本书,涉及到了插件系统的很多底层内容,其中关于插件引擎的设计尤其值得学习。近来,我将自己当年实现的那个例子进行了一个总结,和大家一起分享。

1.插件式框架的组成

(1).框架分为宿主程序和插件对象两部分

(2).两部分交互基于一种公共的通信契约

(3).宿主程序可以独立存在

2.使用插件的原因

(1).可以在无需对程序进行重新编译和发布的条件下扩展程序的功能

(2).可以在不需要程序源代码的环境下为程序增加新的功能

(3).在一个程序的业务逻辑不断发生改变、新的规则频频加入时能够灵活适应

3.插件的一般实现技术

(1).基于动态链接库DLL的插件

(2).基于COM的插件

(3).基于反射技术的插件

4.细谈本框架的实现

4.1.设计全部并实现部分接口

接口分为:

宿主接口:IApplicaiton

插件接口:IPlugin(ICommand,Itool, IMenuDef,IToolBarDef,IDockableWindowDef)和不是继承于Ipluging的IItemDef

本章中,对继承于IApplication的Application和继承于ItemDef的ItemDef类进行了实现。类图如下:

4.2制作插件容器

在实例化的插件还没有被添加到宿主中时,需要一个寄存这些实例化的插件的宿主。

于是,我们在设计完插件接口后,还得做一个设计插件容器的工作。此容器只能存放继承于Iplugin的类。

4.2.1设计PluginCollection

首先:

继承CollectionBase抽象类。

因为CollectionBase已经实现了Ilist,Icolloction和Ienumerable等三个接口,为我们解决了大部分问题。

(其中主要重点是要覆盖一个新的GetEnumerator()方法,且此方法返回的是一个实现了IEnumerator接口的类.如果在重写这个方法时已经利用yield实现了迭代功能,则第二步可以跳过)。

然后:

写那个继承并实现了IEnumerator接口的类。(主要是重写Current,MoveNext,,Reset三个函数)

4.3设计PluginEngine中的反射机制

以上我们设计了通讯接口和接口容器,为什么说插件只有实现了这些接口中的一个才能被识别呢?

因为我们的接口引擎(PluginEngine)只能对这些接口进行识别。

那么何为接口引擎呢?

简单点说,在本系统中,就是利用反射后得到的每个TYPE的InterFace必须是我们以上规定的几个接口才能被识别和做出反应。

4.3.1细解动态加载和对象生成

反射机制是我们这个插件系统的核心技术。

它使得这些类都可以被动态加载和调用。

(1).本系统首先利用Directory.GetFiles()函数得到目标文件夹里的所有DLL文件。

(2).利用反射函数Assemly.LoadFrom加载文件(得到若干程序集)。再利用程序集的GetTypes()得到Type[]数组。

(3).最后利用Type类的GetInterfaces()得到每一个类所继承的接口。利用switch检查这个类是否继承过自定义的那些接口。若实现过,则利用Activator.CreateInstance(Type _type)这个方法来实例化这个类。最后将其加入到插件容器PluginCollection中。

4.4插件的分类

设置五个接口字典容器,分别是装ICommand,ITool,IToolBarDef,IMenuDef,IDockableWindowDef的五个容器和一个命令类型容器(其中将存放实现了ICommand和或者ITool的不重复的Category)。

注:这些容器中的Key值都是在实现这些接口的插件的名字。

4.5建立宿主框架

利用第三方控件Janus WinForms Controls V3.5来设计界面。

此三方控件中有两个控件,一个是UICommandManager,一个是UIPanelManager,这两个控件对插件的插入显示有很大的帮助

此宿主实例化时,首先实例化一个Apllication类,然后再给此实例中的MapControl,PageControl,MainPlantform的重要属性赋值。

所以通过这个被复制了的实例,宿主和插件的交互就不难实现了。

4.6插件获取

这是一个比较大的方面,也是核心之一了。也便是,怎么样能让宿主得到还保留在插件容器中的插件,并能显示在宿主中?

1.因为Command和Tool在UI上是同一类型,所以合在一起获取。

获取中,有两个地方要注意:一个是要使实例Create(hook ),即把宿主的相关信息类Application传递过去。第二个是,注册系统定义事件。例如UICommand+=new CommandEventHandler(UICommand_Click);

2.同理分别对继承了IMenuDef,IToolBarDef以及IDockableWindowDef的对象进行获取。

注:浮动窗体是由UIPanelManager进行托管的。也就是将悬浮框中的ChildHWND(Control类)加入到新panel中的panelContainer.Controls中。

4.7插件对象的事件处理

上一个步骤中,我们把一个未定义的事件处理方法通过自带委托注册到了Click事件中了。

那么这一节我们将具体来写这个事件处理方法。Command是交互的,Tool是不交互的。所以编写起来有很大差别。

这两个处理函数中,有两个共同的关键点:一个是利用e(CommandEventArgs类)的e.Command.Key得到在相关插件字典容器中放置的对象。第二个是都要触发对象的Click函数。

4.8框架插件设计

这节是系统以后也可以继续扩充的地方。

此处重点抓住cAddData这个插件的实现。

此类首先继承Icommand这个接口。在宿主窗体加载获取各插件而触发的create(Iapplication hook)方法中,调用Engine自带的ControlsAddDataCommandClass()类,并将其hook到传递过来的宿主的MapControl上去即可。

4.9宿主程序的高级设计

可以对宿主程序本身进行一些高级设计。比如使得mapControl和PageControl联动显示。比如制定TocControl的浮动菜单或者开发要素数据的查询显示等。

注意:此些设计都是对宿主本身而设计的,跟插件没关系。是最大程度上的利用宿主窗体本身。

4.10框架辅助组件框架库设计

此节完全是为了更方便的开发框架或其插件本身而设计的。

在此部分,可以把很多以后可能会用到的方法进行编写以及封装,以后开发便可以直接调用。

可以称本部分为系统开发包(SDK),但是此部分并非系统必备。

4.11系统发布

系统发布时首先要确定一个空机器上需要运行此系统起码需要哪些基本的平台。

此系统运行时对方机器上起码该装有:.NET 3.0 Framework可再分发组件包,Janus System UI V3.5 和ArcGIS Engine10 Runtime

然后利用InstallShield Express X来打包。

5结果展示

6.本框架的优劣及展望

6.1优势

本框架为纯底层开发,移植性和通用性比较好。具有一般的插件所具有的其他特点,例如易扩展,有一定的解耦性。符合面向接口和依赖倒转的编程思想,在本框架中,还集成了命令模式、观察者模式、遍历模式以及外观模式,单例模式。

6.2劣势

本框架划分的粒度太细,这样容易使类爆炸式增长。

本框架只实现了插件与宿主之间的通信,而没有实现插件与插件之间的通信。

6.3展望

解决插件与插件之间的通信,可单独做一个复杂通信的插件,然后其他插件均引用此插件。利用观察者模式,在宿主中加载插件后,便能实现事件注册,进而实现插件之间的通信。

同时,很多框架都实现了插件的编程思想。比利用Spring的依赖注入和微软提供的MEF所有的依赖注入,均能实现插件系统。

-----欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/

如果您觉得本文确实帮助了您,可以微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^

                                    

(1)从底层设计,探讨插件式GIS框架的实现的更多相关文章

  1. 插件式Web框架

    转载构建高性能插件式Web框架 基于MVC插件模式构建支持数据库集群.数据实时同步.数据发布与订阅的Web框架系统.如下图: 1.基于插件式开发 采用插件模式开发的优点是使得系统框架和业务模式有效地进 ...

  2. Asp.net MVC 插件式应用框架

    Asp.net MVC 插件式应用框架 2013年05月13日 10:16供稿中心: 互联网运营部 摘要:这几年来做了很多个网站系统,一直坚持使用asp.net mvc建站,每次都从头开始做Layou ...

  3. 构建高性能插件式Web框架

    基于MVC插件模式构建支持数据库集群.数据实时同步.数据发布与订阅的Web框架系统.如下图: 1.基于插件式开发 采用插件模式开发的优点是使得系统框架和业务模式有效地进行分离,系统更新也比较简单,只需 ...

  4. [连载]《C#通讯(串口和网络)框架的设计与实现》-2.框架的总体设计

    目       录 C#通讯(串口和网络)框架的设计与实现... 1 (SuperIO)- 框架的总体设计... 1 第二章           框架总体的设计... 2 2.1           ...

  5. 基于Flask的Web应用程序插件式结构开发

    事实上,很多应用程序基于插件式结构开发,可以很方便了扩展软件的功能,并且这些功能完全可以依托于第三方开发者,只要提供好接口和完备文档,比如wordpress.谷歌火狐浏览器等. Python这样的动态 ...

  6. 使用 SailingEase WinForm 框架构建复合式应用程序(插件式应用程序)

    对于一些较小的项目,具备一定经验的开发人员应该能够设计和构建出便于进行维护和扩展的应用程序.但是,随着功能模块数量(以及开发维护这些部件的人员)的不断增加,对项目实施控制的难度开始呈指数级增长. Sa ...

  7. Android应用插件式开发解决方法

    转自:http://blog.csdn.net/arui319/article/details/8109650 一.现实需求描述 一般的,一个Android应用在开发到了一定阶段以后,功能模块将会越来 ...

  8. C#实现插件式架构的方法

    插件式架构,一种全新的.开放性的.高扩展性的架构体系.插件式架构设计近年来非常流行,基于插件的设计好处很多,把扩展功能从框架中剥离出来,降低了框架的复杂度,让框架更容易实现.扩展功能与框架以一种很松的 ...

  9. AvalonDock 2.0+Caliburn.Micro+MahApps.Metro实现Metro风格插件式系统(一)

    随着IOS7由之前UI的拟物化设计变为如今的扁平化设计,也许扁平化的时代要来了,当然我们是不是该吐槽一下,苹果什么时候也开始跟风了,自GOOGLE和微软界面扁平化过后,苹果也加入了这一队伍. Aval ...

随机推荐

  1. 正确获取访问者ip

    使用$_SERVER['REMOTE_ADDR']获取访问者ip具有局限性.比如访问者系统位于docker环境时,$_SERVER['REMOTE_ADDR']获取到的ip为虚拟ip,而不是我们真正需 ...

  2. 怎么可以让div自适应屏幕的高度?(已解决)

    主要解决问题的方法是用JS脚本. 先看布局, 一个div是首部,另一个div是主体,主体包含左侧菜单和右侧内容. 我想把主体div的高度自适应屏幕剩余区域,怎么做? 首先,获取可见区域的高度,docu ...

  3. USACO翻译:USACO 2014 DEC Silver三题

    USACO 2014 DEC SILVER 一.题目概览 中文题目名称 回程 马拉松 奶牛慢跑 英文题目名称 piggyback marathon cowjog 可执行文件名 piggyback ma ...

  4. WinForm窗体 SSK 界面的使用

    1.下载 SSk文件 找到  IrisSkin2.dll 文件和.SSK结尾的文件    为了防止万一粘贴到项目的bin>Debug下面 2. 打开工具箱   添加一个选项卡 3. 添加选择项& ...

  5. ubuntu下 编译安装swftools

    1.下载:http://www.swftools.org/download.html2.安装: tar -zvxf swftools-0.x.x.tar cd swftools-0.x.x ./con ...

  6. Java演算法之快速排序法

    1 * 快速排序法(Quick Sort),遞迴版本. 2 * 3 * @param array 傳入要排序的陣列 4 * @param start 傳入要排序的開始位置 5 * @param end ...

  7. 译文---C#堆VS栈(Part One)

    前言 本文主要是讲解C#语言在内存中堆.栈的使用情况,使读者能更好的理解值类型.引用类型以及线程栈.托管堆. 首先感谢原文作者:Matthew Cochran 为我们带来了一篇非常好的文章,并配以大量 ...

  8. Orchard 微软CMS项目介绍

    我之前的项目中使用了Orchard, 它依据依赖注入的思想而做的模块化让我深深为之着迷,这里开始宣传一下这个架构. 包含的概念非常之多,我现在也不甚了解.Orchard就是自己想控制它改变它的话需要非 ...

  9. 如何让用户只能访问特定的数据库(MSSQL)

    背景 客户的SQL Server实例上有多个厂商的数据库,每个数据库由各自的进行厂进行商维护, 为了限定不同厂商的维护人员只能访问自己的数据库,现需要给各个厂商限定权限,让他们登录SQL Server ...

  10. OpenGL学习资料汇总

    我学OpenGL的3D编程也有1.2个年头了,走了很多弯路,也算有点收获.现在整理出一些好用的资料如下. NeHe OpenGL教程中文版 地址(http://www.yakergong.net/ne ...