




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
VisualC#插件构架实战一、引言问题的引入假设你设计的程序已经部署到用户的计算机上,并且能够正常运行了。但是有一天,用户打来了电话——他们要求增加新的功能。确定了用户的需求后,你竟然发现原有的软件架构已经无法胜任新增任务的需求——你需要重新设计这个应用了!但问题是,就算你又用了一个开发周期完成了用户需要的应用,却不能保证用户的需求不会再次变更。也就是说,需求蔓延的可能性依然存在。因此,这种情况下插件构架更能显示出它的优越性。几个解决方案的对比我总结了一下我所接触到的插件构架,大致上可分为以下几类:i>脚本式使用某种语言把插件的程序逻辑写成脚本代码。而这种语言可以是Python,或是其他现存的已经经过用户长时间考验的脚本语言。甚至,你可以自行设计一种脚本语言来配合你程序的特殊需要。当然,用当今最流行的XML是再合适不过了。这种形式的特点在于,稍有点编程知识的用户就可以自行修改你的脚本(a_a假如你不加密它的话)。我们无法论证这是好处还是坏处。因为,这种情况所造成的后果是不可预知的。ii>动态函数库DLL插件功能以动态库函数的形式存在。主程序通过某种渠道(插件编写者或某些工具)获得插件DLL中的函数签名,然后在合适的地方调用它们。用过Matlab的读者都知道,Matlab中的各项功能几乎都是些动态链入的函数。iii>聚合式顾名思义,就是把插件功能直接写成EXE。主程序除了完成自己的职责外,还负责调度这些“插件”。我不喜欢这种形式。这使插件与插件之间,主程序与插件之间(主要是这一点)的信息交流困难了许多。巴比伦塔的失败[1]从某种程度上讲就是信息交流无法实现造成的。iv>COM组件COM[2]的产生给这个世界增添了几分活力。只有接口!我们的插件需要做的只是实现程序定义的接口。主程序不需要知道插件怎样实现预定的功能,它只需要通过接口访问插件,并提供主程序相关对象的接口。这样一来,主程序与各插件之间的信息交流就变得异常简单。并且,插件对于主程序来说是完全透明的。3.决策C#是面向对象的程序设计语言。它提供了interface关键字来直接定义接口。同时,System.Reflection命名空间也提供了访问外部程序集的一系列相关对象。这就为我们在C#中实现插件构架打下了坚实的基础。下面,我们将以一个具有插件构架的程序编辑器为例,来阐述这种构架在C#中的实现。二、设计过程好了,现在我们准备把所有的核心代码都放在CSPluginKernel命名空间中。用VSIDE建立一个C#类库工程。在命名空间CSPluginKernel中开始我们的代码。1.接口设计我们的程序编辑器会向插件开放正在编辑的文档对象。程序启动后,就枚举每一个插件并把它连接到主程序,同时传递主程序对象的接口。插件可以通过这个接口来请求主程序对象或访问主程序功能。根据上面的需求,我们首先需要一个主程序接口:publicinterfaceIApplicationObject(voidAlert(stringmsg);//产生一条信息voidShowInStatusBar(stringmsg);//将指定的信息显示在状态栏IDocumentObjectQueryCurrentDocument();//获取当前使用的文档对象IDocumentObject[]QueryDocuments();//获取所有的文档对象//设置事件处理器voidSetDelegate(DelegateswhichOne,EventHandlertarger);}//目前只需要这一个事件publicenumDelegates(Delegate_ActiveDocumentChanged,}然后是IDocumentObject接口。插件通过这个接口访问编辑器对象。//////编辑器对象必须实现这个接口///publicinterfaceIDocumentObject(//这些属性是RichTextBox控件的相应的属性映射stringSelectionText(get;set;}ColorSelectionColor(get;set;}FontSelectionFont(get;set;}intSelectionStart(get;set;}intSelectionLength(get;set;}stringSelectionRTF(get;set;}boolHasChanges(get;}voidSelect(intstart,intlength);voidAppendText(stringstr);voidSaveFile(stringfileName);voidSaveFile();voidOpenFile(stringfileName);voidCloseFile();_} 这个接口不需要过多解释。这里我只实现了RichTextBox控件少数的几个方法,其他可能用得到的,读者自行添加即可。再然后,根据插件在其生命周期里的行为,设计插件的接口。//////本程序的插件必须实现这个接口///publicinterfaceIPlugin(ConnectionResultConnect(IApplicationObjectapp);voidOnDestory();voidOnLoad();voidRun();}//////表示插件与主程序连接的结果///publicenumConnectionResult(Connection_Success,Connection_Failed}主程序会首先调用Connect。方法,并传递IApplicationObject给插件。插件在这个过程中做一些初始化工作。然后,插件的OnLoad()方法被调用。在这之后,当主程序接收到调用插件的信号时(键盘鼠标响应)就会调用插件的Run()方法来启动这个插件。程序结束时,调用其OnDestory()方法。这样,插件的生命才宣告结束。2.插件信息的存储与获取一个插件需要有它的名称、版本等信息。作为设计者的你,也一定要留下你的尊姓大名和个人网站等用来宣传自己。C#的新特性一一属性,就是一个很好的解决方案。因此我们定义一个从System.Attribute继承来的类PluginInfoArrtibute://////用来指定一个插件的相关信息IIIpublicclassPluginInfoAttribute:System.Attribute(//////Deprecated.Donotuse.///publicPluginInfoAttribute。{}publicPluginInfoAttribute(stringname,stringversion,stringauthor,stringwebpage,boolloadWhenStart){//细节已略去}publicstringName{get{return_Name;}}publicstringVersion{get{return_Version;}}publicstringAuthor{get{return_Author;}}publicstringWebpage{get{return_Webpage;}}publicboolLoadWhenStart{get{return_LoadWhenStart;}}//////用来存储一些有用的信息///publicobjectTag{get{return_Tag;}set{_Tag=value;}}//////用来存储序号///publicintIndex{get{return_Index;}set{_Index=value;}}privatestring_Name="";privatestring_Version="";privatestring_Author="";privatestring_Webpage="";privateobject_Tag=null;privateint_Index=0;//暂时不会用privatebool_LoadWhenStart=true;}用这个类修饰你的插件,并让他实现IPlugin接口://////MyPluging1(Justfortest)///[PluginInfo("MyPluging1(Justfortest)","1.0","JackHHansen","/matrix2003b",true)]publicclassMyPlugin1:IPlugin(publicMyPlugin1()(}#regionIPlugin成员//细节已略去#endregionprivateIApplicationObject_App;privateIDocumentObject_CurDoc;}加载插件现在就得用到System.Refelction命名空间了。程序在启动时会搜索plugins目录下的每一个文件。对于每一个文件,如果它是一个插件,就用Assembly对象加载它。然后枚举程序集中的每一个对象。判断一个程序集是否为我们的插件的方法是判断它是否直接或间接实现自IPlugin。用下面的函数,传递从程序集枚举的对象的System.Type。privateboolIsValidPlugin(Typet)(boolret=false;Type[]interfaces=t.GetInterfaces();foreach(TypetheInterfaceininterfaces)(if(the
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025共同担保借款合同书模板
- 2025新农村建设项目:污水处理设施施工承包合同
- 2025关于出版社与作者版权转让合同
- 2025劳动合同法辞职规定
- 《2025年的青岛房屋租赁合同》
- 2025供应商与分销商合作合同模板
- 2025 水产品买卖合同
- 幼儿园中班课程艺术造飞机
- 2025租房合同书格式样本
- 2025商业办公房买卖合同模板
- 七类作业JSA分析记录表格模板
- 心理统计学考研历年真题及答案
- 2022年中国石油大学《化工原理二》完整答案详解
- 技术经纪人练习题集附有答案
- 内科学讲义(唐子益版)
- GB/T 4357-2022冷拉碳素弹簧钢丝
- GB/T 19845-2005机械振动船舶设备和机械部件的振动试验要求
- GB/T 14614-1993小麦粉吸水量和面团揉和性能测定法粉质仪法
- 酱酒行业发展趋势分析
- 《红楼梦》贾府平面图
- 养老机构全套服务管理流程图()
评论
0/150
提交评论