(1)从底层设计,探讨插件式GIS框架的实现
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处: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框架的实现的更多相关文章
- 插件式Web框架
转载构建高性能插件式Web框架 基于MVC插件模式构建支持数据库集群.数据实时同步.数据发布与订阅的Web框架系统.如下图: 1.基于插件式开发 采用插件模式开发的优点是使得系统框架和业务模式有效地进 ...
- Asp.net MVC 插件式应用框架
Asp.net MVC 插件式应用框架 2013年05月13日 10:16供稿中心: 互联网运营部 摘要:这几年来做了很多个网站系统,一直坚持使用asp.net mvc建站,每次都从头开始做Layou ...
- 构建高性能插件式Web框架
基于MVC插件模式构建支持数据库集群.数据实时同步.数据发布与订阅的Web框架系统.如下图: 1.基于插件式开发 采用插件模式开发的优点是使得系统框架和业务模式有效地进行分离,系统更新也比较简单,只需 ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》-2.框架的总体设计
目 录 C#通讯(串口和网络)框架的设计与实现... 1 (SuperIO)- 框架的总体设计... 1 第二章 框架总体的设计... 2 2.1 ...
- 基于Flask的Web应用程序插件式结构开发
事实上,很多应用程序基于插件式结构开发,可以很方便了扩展软件的功能,并且这些功能完全可以依托于第三方开发者,只要提供好接口和完备文档,比如wordpress.谷歌火狐浏览器等. Python这样的动态 ...
- 使用 SailingEase WinForm 框架构建复合式应用程序(插件式应用程序)
对于一些较小的项目,具备一定经验的开发人员应该能够设计和构建出便于进行维护和扩展的应用程序.但是,随着功能模块数量(以及开发维护这些部件的人员)的不断增加,对项目实施控制的难度开始呈指数级增长. Sa ...
- Android应用插件式开发解决方法
转自:http://blog.csdn.net/arui319/article/details/8109650 一.现实需求描述 一般的,一个Android应用在开发到了一定阶段以后,功能模块将会越来 ...
- C#实现插件式架构的方法
插件式架构,一种全新的.开放性的.高扩展性的架构体系.插件式架构设计近年来非常流行,基于插件的设计好处很多,把扩展功能从框架中剥离出来,降低了框架的复杂度,让框架更容易实现.扩展功能与框架以一种很松的 ...
- AvalonDock 2.0+Caliburn.Micro+MahApps.Metro实现Metro风格插件式系统(一)
随着IOS7由之前UI的拟物化设计变为如今的扁平化设计,也许扁平化的时代要来了,当然我们是不是该吐槽一下,苹果什么时候也开始跟风了,自GOOGLE和微软界面扁平化过后,苹果也加入了这一队伍. Aval ...
随机推荐
- 2016huasacm暑假集训训练五 C-Common Subsequence
题目链接:http://acm.hust.edu.cn/vjudge/contest/126708#problem/C 题意:这是一道求字符串的公共子串的最大长度的题目,用dp动态方程即可 if(a[ ...
- Centos 6.5 搭建l2tp 服务端和客户端
废话不多说直接上步骤. server #epel仓库愿安装 rpm -ivh http://mirrors.ustc.edu.cn/fedora/epel/6/x86_64/epel-release- ...
- phpcms v9常用方法
1.联动菜单根据地区id显示地区名称的方法: 显示效果: 四川 >> 攀枝花 >> 仁和区 [字段名字为 area] {get_linkage($info['area'],1, ...
- Javascript基础回顾 之(二) 作用域
本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对Javascript的一些基本原理普遍存在这里或者 ...
- 剑指Offer面试题:32.数字在排序数组中出现的次数
一.题目:数字在排序数组中出现的次数 题目:统计一个数字在排序数组中出现的次数.例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4. 二.解题思路 2 ...
- Android什么时候进行View中Background的加载
对大多数Android的开发者来说,最经常的操作莫过于对界面进行布局,View中背景图片的加载是最经常做的.但是我们很少关注这个过程,这篇文章主要解析view中背景图片加载的流程.了解view中背景图 ...
- java反射 之 反射基础
一.反射 反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...
- Leetcode-268 Missing Number
#268. Missing Number Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find ...
- div非弹出框半透明遮罩实现全屏幕遮盖css实现
IE浏览器下设置元素css背景为透明: background-color: rgb(0, 0, 0); filter: alpha(opacity=20); 非IE浏览器下设置元素css背景为透明: ...
- SSISDB6:Operation
SSISDB使用Operation表示对SSIS Project所做的任何操作,在执行一次Operation时,SSISDB会记录Operation的Message,当触发Event时,会记录Even ...