刘金雨

凡所有相,皆是虚妄,若见诸相非相,即见如来

刘金雨ID:passos
40302次访问,排名2622好友5人,关注者11
老程序员。。。
passos的文章
原创 13 篇
翻译 1 篇
转载 8 篇
评论 84 篇
古月春秋的公告

敝人姓刘,名云涛,字金雨。

古月春秋的专栏
最近评论
passos:编译倒是过了,不过这好几年了,找找看。。。
829939:不知道您重新编译过了没

发出来分享一下啊

这个bug让mysql5用起来很烦人的
ddd:不知道楼上的哥哥,哪位知道从那里下载SharpDevelop的源码呢?我从上面的地址连接过去,告诉我"找不到服务器"
passos:Believe or not, as a developer in this team, I do not know this international release before it does...maybe it is sound funny, but that is fact.

In my personal opinion, the release actio……
古月春秋:TO:AJU
如果要在工具栏中插入一个新的功能。也就是新做一个插件,一般的来说要这么几个步骤:
1、确定你的插件是哪种类型的,找到对应的Codon接口/抽象类继承
2、实现Codon中的抽象方法,也就是你的插件功能
3、找到对应的扩展点,在配置文件中把你的插件挂到这个扩展点下面去

例如你要在工具栏中加入一个按钮,那么可以先从配置文件中查找一下……
文章分类
收藏
相册
存档
订阅我的博客
XML聚合  FeedSky

原创 SharpDevelop源码分析 (二、主程序+隐藏的初始化)收藏

新一篇: SharpDevelop源码分析 (三、插件系统)  | 旧一篇: SharpDevelop源码分析 (一、序+基本概念)

二、主程序

    在大学课程里面,我对于模拟电路总是搞不清楚,直到现在也是这样。我总觉得电路图很奇怪,总会问“这部分电路是做什么用的”、“为什么会有这样的效果”。在我的脑海里面,每部分的电路都应该有一定的用处,可是我总是看不明白。我妈妈说,我的思路被软件所固化的太久了,看电路图不应该总是一个个模块的看,正确的方法应该是从电源的一极顺着电路看,一直看到电源的另一极。我现在仍然不懂看电路图,可是以我看代码的经验来说,我觉得分析源代码按照这样的思路来看会比较容易把脉络理清楚。
     在SharpDevelop的代码中,由于很多的接口和插件的原因,很多代码在看到某个地方会突然失去函数/方法调用的线索。例如看某个函数的实现的时候会跳到一个接口里面去,那是因为这部分功能在运行期才会给一个实现了这个接口的对象来进行具体的执行。从这个角度来说,设计模式也给我们研究代码稍微带来了一点小小的难度。在看Linux下源代码的时候也经常遇到这种问题,在这个时候寻找代码线索比较好的方法是用一个文本搜索工具来搜索相关的关键字。在Linux下我经常会用grep,Windows下面类似UltraEdit的“批量文件查找”功能会很好用(或者“Search And Replace”之类的工具)。这个是我读代码的一点小小的经验,如果你知道有更好的方法,请告诉我让我也学习一下 ? 。
     我不想大段大段的贴代码出来占地方(空间、带宽,还有各位看官的注意力),在需要的地方我会贴上主要的代码,因此最好能够找代码来对应着看。把代码包解压缩,我把它解到了“F:\SharpDevelop”(如果没有说明,下文都是以此为代码的根目录了)。由于SharpDevelop本身对于察看代码不是很方便,没有“转到定义”之类的功能,因此我建议你把它的代码转成VS的工程来看。不过很可惜,SharpDevelop的工程导出功能现在有问题,如果导出\src\SharpDevelop.cmbx 这个总的复合工程的话会失败(我记得RC1版本是可以成功的,不知道为什么后来的版本反而会出问题),所以只能一个一个工程的导出。
     好了,让我们来看SharpDevelop的代码吧。
1、起点
    在主程序的起点在\src\Main\StartUp\SharpDevelopMain.cs,找到Main函数这就是整个程序的起点了。开始的部分是显示封面窗体并加上命令行控制,其中SplashScreenForm 定义在\src\Main\Base\Gui\Dialogs\SplashScreen.cs文件中,这部分我就不多说了。之后是

Application.ThreadException += new ThreadExceptionEventHandler(ShowErrorBox);

    SharpDevelop为了有效的进行错误报告,因此自己进行了异常的控制。系统出现异常的时候,SharpDevelop会拦截下来弹出它自己的异常提示报告对话框。这个代码就是在这一行实现的。其中 ShowErrorBox 这个方法就在类SharpDevelopMain中,ExceptionBox 定义在\src\Main\StartUp\Dialogs\ExceptionBox.cs中。如果需要进行自己的异常控制,可以学习一下这里的技巧。

2、充满玄机的初始化

string [] addInDirs = ICSharpCode.SharpDevelop.AddInSettingsHandler.GetAddInDirectories( out ignoreDefaultPath );
AddInTreeSingleton.SetAddInDirectories(addInDirs, ignoreDefaultPath);

    通过AddInSettingsHandler取得插件的目录,并告知AddInTreeSingleton。AddInSettingsHandler定义在\src\Main\StartUp\Dialogs\AddInTreeSettingsHandler.cs中,它通过读取系统配置(App.config)文件中的AddInDirectory节点的Path属性来确定插件的目录位置,或者你也可以通过自己定义的AddInDirectories节来指定插件目录。如果你没有做这些配置,默认的目录在SharpDevelop运行目录的..\Addins目录下。

ServiceManager.Services.AddService(new MessageService());
ServiceManager.Services.AddService(
new ResourceService());
ServiceManager.Services.AddService(
new IconService());

    通过ServiceManager(服务管理器)加入三个系统默认的服务,消息服务、资源服务、图标服务。这三个服务中,消息服务是显示各种信息提示,另外两个是属于系统的资源,SharpDevelop通过服务来进行统一调用和管理。
ServiceManager.Services.InitializeServicesSubsystem("/Workspace/Services");

    初始化其他的服务。SharpDevelop把服务定义在插件树的/Workspace/Services这个路径中,凡是在这个路径下的插件都被认为是服务,因此如果你自己定义了一个服务的话,也需要挂到这个路径下(这里就是系统服务的扩展点了)。

    注意!这一步中,在我们的眼皮子底下悄悄的进行了一个重要的初始化工作。各位看官请看,ServiceManager 定义在\src\Main\Core\Services\ ServiceManager.cs文件中,察看它的InitializeServicesSubsystem方法,我们发现这样一行

AddServices((IService[])AddInTreeSingleton.AddInTree.GetTreeNode(servicesPath).BuildChildItems(this).ToArray(typeof(IService)));

    在这里,AddInTreeSingleton首次调用了AddInTree(插件树)的实例。按照Singleton模式,只有在首次调用的时候才会初始化实例,这里也是同样如此。整个系统的AddInTree是在这一步中进行了初始化工作,稍候我们将详细介绍AddInTree如何进行初始化工作,先顺便看看服务的初始化。在ServiceManager的InitializeServicesSubsystem方法中,通过AddInTree检索服务插件路径下的所有配置,并通过它来读取、建立具体的对象,然后加入到服务列表中。之后通过一个循环,逐个的调用各个服务的InitializeService方法初始化服务。

    AddInTree的初始化工作容我们稍候再看,先把主体的代码看完。

commands = AddInTreeSingleton.AddInTree.GetTreeNode("/Workspace/Autostart").BuildChildItems(null);
for (int i = 0; i < commands.Count - 1; ++i)
{
 ((ICommand)commands[i]).Run();
}

    /Workspace/Autostart是系统自动运行命令的扩展点路径,定义在这个路径下的插件会在系统启动的时候自动运行。在这里,通过插件树初始化建立处于这个路径下的Command(命令),并逐一执行。BuildChildItems方法的功能是建立这个扩展点下的Command列表,我会在介绍AddTree的时候具体说明它的实现。

     主程序代码的最后,初始化完毕、关闭封面窗体,然后执行命令列表中最后一个命令(也就是系统的主界面)。在主界面退出的时候,系统卸载所有的服务。

    在这部分代码中,我们知道了两个系统指定的扩展点路径 /Workspace/Services 和 /Workspace/Autostart ,我们实现服务和指定系统自动运行命令的时候就可以挂到这两个扩展点路径下了。
     托反射的福,ServiceManager.Services可以通过类型(接口)来查找具体的实例,也就是GetServices方法。但是ServiceManager的具体实现我们可以容后再看,这里已经不是最紧要的部分了。
     接下来,我们来看看整个插件系统的核心-AddinTree的代码,看看它是如何通过插件配置进行初始化并建立起整个系统的插件树骨干。

发表于 @ 2004年10月07日 20:10:00|评论(loading...)|编辑

新一篇: SharpDevelop源码分析 (三、插件系统)  | 旧一篇: SharpDevelop源码分析 (一、序+基本概念)

评论

#tony 发表于2004-10-08 13:19:00  IP: 210.22.128.*
支持楼主,可惜现在没有那本书在身边,代码也没有,看得一头雾水。。
结合代码看应该不错。
#tony 发表于2004-10-08 13:19:00  IP: 210.22.128.*
支持楼主,可惜现在没有那本书在身边,代码也没有,看得一头雾水。。
结合代码看应该不错。
#qq7good 发表于2004-10-08 11:24:00  IP: 61.177.35.*
好,继续哦
#SW515 发表于2004-10-09 08:40:00  IP: 61.144.207.*
楼主,文章写得不错,做个友情链接罢。
http://blog.csdn.net/SW515
#gully 发表于2004-10-09 09:06:00  IP: 61.189.161.*
分析得很好~
如果从整来分析SD会更好一些. 感觉你的这种分析方法就是在看电路图勒 :)
#gully 发表于2004-10-09 09:06:00  IP: 61.189.161.*
分析得很好~
如果从整体来分析SD会更好一些. 感觉你的这种分析方法就是在看电路图勒 :)
#Kozen 发表于2004-10-09 09:47:00  IP: 218.94.30.*
动作挺快的呀!不过还想你能更快些!:)继续加油啊。
我也在抽空看SD,只是暂时没时间写心得。有机会大家可以交流一下。
顺便说一下,SD怎么连一个IDE最基本的Debug功能都没有啊!遗憾!不过值得学习的地方还是很多的,如WinForm的界面设计及其代码生成等。
#古月春秋 发表于2004-10-09 17:18:00  IP: 220.163.13.*
TO: gully
哎,刚开始看代码,先这样顺着找线索,找到一定程度就可以回过头来从整体上来看了 :)

TO:Kozen
谢谢,不过在网吧上网实在很痛苦
#zerosky 发表于2004-10-09 10:04:00  IP: 210.95.250.*
写得不错!有意思
正在看SD 源码,
期待下一篇大作
#tommy 发表于2004-10-13 17:54:00  IP: 220.200.168.*
支持 支持~!~!~
我正在看SD源码 热切期待下一篇大作!!!!!!~
发表评论  


登录
Csdn Blog version 3.1a
Copyright © 古月春秋