SharpDevelop源码分析 (三、插件系统)

本文深入探讨SharpDevelop的插件系统,分析了插件配置、插件树的结构和核心组件AddIn与AddInTree。通过示例展示了如何通过配置文件创建和管理插件,阐述了Codon和Command的关联,以及插件初始化过程。同时提出了在构建插件树过程中处理依赖失败和实现插件热部署的思考问题。
摘要由CSDN通过智能技术生成


三、插件系统

   上回书说到SharpDevelop入口Main函数的结构,ServiceManager.Service在InitializeServicesSubsystem方法中首次调用了AddInTreeSingleton的AddInTree实例,AddInTree在这里进行了初始化。本回进入AddInTree着重讲述SharpDevelop的插件系统。在叙述的时候为了方便起见,对于“插件”和插件具体的“功能模块”这两个词不会特别的区分,各位看官可以从上下文分辨具体的含义(而事实上,SharpDevelop中的“插件”是指.addin配置文件,每一个“插件”都可能会包含多个“功能模块”)。

1、插件的配置
   既然说到插件系统,那么我们先来看一看SharpDevelop插件系统的组织形式。
   很多时候,同一个事物从不同的角度来看会得出不一样的结论,SharpDevelop的插件系统也是如此。在看SharpDevelop的代码以前,按照我对插件的理解,我认为所谓的“插件”就是代表一个功能模块,插件的配置就是描述该插件并指定如何把这个插件挂到系统中。SharpDevelop中有插件树的思想,也就是每一个插件在系统中都有一个扩展点的路径。那么按照我最初对插件的理解,编写插件需要做的就是:
   A、根据插件接口编写功能模块实现一个Command类
   B、编写一个配置文件,指定Command类的扩展点(Extension)路径,挂到插件树中

   之后按照这样的理解,我编写了一个察看插件树的插件AddinTreeView,打算挂到SharpDevelop中去。根据SharpDevelop对插件的定义,我把具体插件的AddinTreeViewCommand实现了之后,编写了一个配置文件AddinTreeView.addin如下:

< AddIn  name         = "AddinTreeView"
       author      
= "SimonLiu"
       copyright   
= "GPL"
       url         
= "http://www.icsharpcode.net"
       description 
= "Display AddinTree"
       version     
= "1.0.0" >

 
< Runtime >
  
< Import  assembly ="../../bin/ AddinTreeView.dll" />
 
</ Runtime >

 
< Extension  path  = "/SharpDevelop/Workbench/MainMenu/Tools" >
  
< MenuItem  id  = "AddinTreeView"  
   label 
= "View AddinTree"  
   class 
= "Addins.AddinTreeView.AddinTreeViewCommand" />
 
</ Extension >  
</ AddIn >


   在配置文件中,Runtime节指定了插件功能模块所在的库文件Addins.dll的具体路径,在Extension节中指定了扩展点路径/SharpDevelop/Workbench/MainMenu/Tools(我是打算把它挂到主菜单的工具菜单下),然后在Extension内指定了它的Codon为 MenuItem以及具体的ID、标签、Command类名。这样做,SharpDevelop运行的很不错,我的插件出现在了Tools菜单下。之后,我又编写了一个SharpDevelop的资源管理器(ResourceEditor)的插件类ResourceEditor.dll并把它挂到Tool菜单下。同样的,我也写了一个ResourceEditor.addin文件来对应。系统工作的很正常。

   如果我们对于每一个插件都编写这样的一个配置文件,那么插件的库文件(.dll)、插件配置文件(.addin)是一一对应的。不过这样就带来了一个小小的问题,在这样的一个以插件为基础的系统中,每一个菜单、工具栏按钮、窗体、面板都是一个插件,那么我们需要为每一个插件编写配置文件,这样就会有很多个配置文件(似乎有点太多了,不是很好管理)。SharpDevelop也想到了这个问题,于是它允许我们把多个插件的配置合并在一个插件的配置文件中。因此,我把我的两个插件库文件合并到一个Addins工程内生成了Addins.dll,又重新编写了我的插件配置文件MyAddins.addin如下:

< AddIn  name         = "MyAddins"
       author      
= "SimonLiu"
       copyright   
= "GPL"
       url         
= "http://www.icsharpcode.net"
       description 
= "Display AddinTree"
       version     
= "1.0.0" >

 
< Runtime >
  
< Import  assembly ="../../bin/Addins.dll" />
 
</ Runtime >

 
< Extension  path  = "/SharpDevelop/Workbench/MainMenu/Tools" >
  
< MenuItem  id  = "ResourceEditor"  
   label 
= "Resource Editor"  
   class 
= "Addins.ResourceEditor.Command.ResourceEditorCommand" />  
  
< MenuItem  id  = "AddinTreeView"  
   label 
= "View AddinTree"  
   class 
= "Addins.AddinTreeView.AddinTreeViewCommand" />  
 
</ Extension >  
</ AddIn >


   这样,我把两个插件的功能模块使用一个插件配置文件来进行配置。同样的,我也可以把几十个功能模块合并到一个插件配置文件中。SharpDevelop把这个插件配置文件称为“Addin(插件)”,而把具体的功能模块封装为Codon,使用Command类来包装具体的功能。SharpDevelop本身的核心配置SharpDevelopCore.addin里面就包含了所有的基本菜单、工具栏、PAD的插件配置。
我们回过头来看一下,现在我们有了两颗树。首先,插件树本身是一个树形的结构,这个树是根据系统所有插件的各个Codon的扩展点路径构造的,表示了各个Codon在插件树中的位置,各位看官可以通过我写的这个小小的AddinTreeView来看看SharpDevelop中实际的结构。其次,插件的配置文件本身也具有了一个树形的结构,这个树结构的根节点是系统的各个插件配置文件,其下是根据这个配置文件中的Extension节点的来构成的,描述了每个Extension节点下具有的Codon。我们可以通过SharpDevelop的Tools菜单下的AddinScout来看看这个树的结构。
我为了试验,把SharpDevelop的插件精简了很多,构成了一个简单的小插件系统。下面是这个精简系统的两个树的截图。各位看官可以通过这两副图理解一下插件树和插件配置文件的关系(只是看同样问题的两个角度,一个是Codon的ExtensionPath,一个是配置文件的内容)。


总结一下SharpDevelop插件的配置文件格式。首先是 <AddIn>节点,需要指定AddIn的名称、作者之类的属性。其次,在AddIn节点下的<Runtime>节点内,使用<Import …>来指定本插件配置中Codon所在的库文件。如果分布在多个库文件中,可以一一指明。然后,编写具体功能模块的配置。每个功能模块的配置都以扩展点<Extension>开始,指定了路径(Path)属性之后,在这个节点内配置在这个扩展点下具体的Codon。每个Codon根据具体不同的实现有不同的属性。各位看官可以研究一下SharpDevelop的核心配置文件SharpDevelopCore.addin的写法,相信很容易理解的。

2、插件系统的核心AddIn和AddInTree
   前文讲到,在SharpDevelop的Main函数中,ServiceManager.Service在InitializeServicesSubsystem方法中首次调用了AddInTreeSingleton的AddInTree实例,AddinTree在这个时候进行了初始化。现在我们就来看看AddInTreeSingleton.AddInTree到底做了些什么事情,它定义在/src/Main/Core/AddIns/AddInTreeSingleton.cs文件中。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 27
    评论
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值