探讨插件式GIS框架的设计

三年前,听当时的师兄推荐,买了蒋波涛的一本关于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所有的依赖注入,均能实现插件系统。

探讨插件式GIS框架的设计,布布扣,bubuko.com

时间: 2024-11-04 13:39:43

探讨插件式GIS框架的设计的相关文章

插件式Web框架

转载构建高性能插件式Web框架 基于MVC插件模式构建支持数据库集群.数据实时同步.数据发布与订阅的Web框架系统.如下图: 1.基于插件式开发 采用插件模式开发的优点是使得系统框架和业务模式有效地进行分离,系统更新也比较简单,只需更新业务插件,不需要动整个框架,开发人员无需关心整个框架结构. 但插件模式调试稍微麻烦一点,比不采用插件模式开发的效率上也要差一点,因为它采用反射进行动态加载插件. 登录插件示例: namespace LoginPlugin { public class Plugin

构建高性能插件式Web框架

基于MVC插件模式构建支持数据库集群.数据实时同步.数据发布与订阅的Web框架系统.如下图: 1.基于插件式开发 采用插件模式开发的优点是使得系统框架和业务模式有效地进行分离,系统更新也比较简单,只需更新业务插件,不需要动整个框架,开发人员无需关心整个框架结构. 但插件模式调试稍微麻烦一点,比不采用插件模式开发的效率上也要差一点,因为它采用反射进行动态加载插件. 登录插件示例: namespace LoginPlugin { public class Plugin : NetUML.Portal

[连载]《C#通讯(串口和网络)框架的设计与实现》- 9.插件引擎设计

目       录 第九章           插件引擎设计... 2 9.1           框架的契约-接口... 2 9.2           插件的雏形-抽象类... 3 9.3           实现接口... 4 9.4           反射机制... 5 9.5           反射工具类... 8 9.6           小结... 9 第九章     插件引擎设计 在介绍<第10章 宿主程序详细设计>之前对接口和插件的相关内容进行一下整体介绍,在设计宿主程

[连载]《C#通讯(串口和网络)框架的设计与实现》- 0.前言

                              目       录 前言 前言 刚参加工作,使用过VB.VC开发软件,随着C#的崛起,听说是C++++,公司决定以后开发软件使用C#,凭借在书市5块钱买C#编程入门书籍,开始了职业生涯.开发C/S.B/S结构的软件是必不可少的,又涉及到Remoting.WebService.线程.异步等不知所云的技术.到现在为止,不敢妄称精通,却也使用熟练:研读Framework源代码,不敢说全部搞懂,却对技术提高有很大帮助. 身在传统行业,确实感觉到

(C/C++)基于SharpUI控件库的插件式框架开发--第一篇简介

看到题目,很明显这里要说的是插件式框架的开发,当然是用c/c++来实现的.开发对于我来说,是一种爱好,但并非科班出身,所以这里要说的一点分享就是,开发并不是会写代码就行了,最主要的是要有思路想法,比如要实现一个功能,就要知道,这个功能到底是要来实现啥的,要实现它需要什么样的算法等等,做到胸中有丘壑,再去用最简单代码去实现它,就会发现写代码是一件很享受的事情. 参加工作快两年了,一开始的是用C#开发,写了半年多的功能和小控件,上手之后,参考ICSharpCode.Core.Presentation

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

对于一些较小的项目,具备一定经验的开发人员应该能够设计和构建出便于进行维护和扩展的应用程序.但是,随着功能模块数量(以及开发维护这些部件的人员)的不断增加,对项目实施控制的难度开始呈指数级增长. SailingEase WinForm 框架为您提供了针对此问题提出的解决方案.在本文中,将对基于SailingEase WinForm 框架的复合应用程序的定义进行解释,并简要说明如何才能构建一个基于 SailingEase WinForm 框架功能的复合应用程序. 传统的单一应用程序 传统的单一应用

插件式框架平台

二.插件式框架平台 以插件编程为指导思想,动态反射调用组件为行动方针,深入调研.设计.编码,初步形成现代化软件架构. 简介 有了理论指导,就需要用实践去验证.所谓知行合一. 作为一款通用插件式开发框架,基础的插件内核是整个平台的核心.鉴于平台的通用性和易用性,还插件式的提供以下常用基础模块功能: 1. 工作流组件 2. 权限系统组件 3. 自动更新组件 4. 自定义UI套件 5. 轻量级ORM 6. 字典管理 7. 通用类库 2.1 插件内核 本平台的插件内核开发借鉴了SD中服务和插件树思想,以

我们一起完成插件框架的设计与实现

原文:我们一起完成插件框架的设计与实现 开场一些题外话,今天登陆这个"小菜"的博客园,感触颇多."小菜"是我以前在QQ群里面的网名,同时也申请了这个博客园账户,五年前的"小菜"在NET和C++某两个群里面非常的活跃,也非常热心的帮助网友尽能力所及解决技术上的问题.依稀记得当时NET群里面的"青菊.Allen.酷酷",C++群里面的"夏老师.风筝兄"等网友.哥们.时过境迁,后来因为某些原因而慢慢淡出了QQ群里

(C/C++)基于SharpUI控件库的插件式框架开发--第三篇框架基础服务库

一个框架基础的东西,一般也是操作的最基础的类,比如char.int.bool等,有时出现内存泄露的问题导致错误的抛出,但是C++开发有的时候就算是抛出异常,那也是靠经验来积累才能非常快速准确的找出错误所在,这就需要在框架中需要添加日志管理的接口,日志管理的好处就是开发者自身在找异常时提供参考,另一个就是如果用户操作时出现问题,也可将日志反馈,帮助快速解决问题:总之了为了更好的扩展完善我的框架,我详细列一下这个基础服务库(XPCore)包含内容: 虽说sharpui控件库内封闭好string类,但