RogerTong's Tech Space

文章书傲骨,程序写春秋

导航

在之前的文章中我们提到了Mussel插件的层次结构:插件(Addin)包括了插件项目的装载节点(AddinNode),装载节点又包括了插件项目(AddinItem),而每个插件项目又可以包括无限下级的子项目:


 

Mussel的加载器在加载时,会尝试读取当前文件夹以下(包含子文件夹)的所有*.addin文件,每个addin文件被Mussel加载器识别、加载后,便会形成如上图所示的IAddin对象,如果每个插件都是独立的,这个过程就非常简单。但是插件之间必须然会有一些联系,例如,如果系统的工具栏是一个稳定的插件(addin),如果金山词霸有一个扩展,能添加一个按钮到系统的工具栏中,我们先来看看摸拟的配置文件,为了方便说明,我们假定ClassKey指示的类型都存在并忽略掉程序集引入的配置部分。

Toolbar的addin配置文件(toolbar.addin

词霸扩展插件的配置(ciba.addin)

分析一下插件配置文件:

首先,词霸的扩展插件无疑是依赖Toolbar插件的,因为他需要在Toolbar上加入新的按钮,所以Toolbar插件的信息必须优先于词霸的插件被系统识别,因此,我们在Addin的元素上用InsertAfter来标识。

另外,由于词霸插件需要放入到ToolBar插件,作为一个子插件出现,所以我们可以看到在 ciba.addin的AddinNode节点有特殊的配置,引入了一个Container。AddinNode的 Path 属性指示插件节点路径的配置,而Container 属性则指示放入该节点的具体哪个插件中作为其子插件,插件的层次以 . 分隔,例如,如果Toolbar插件下面还有一个子插件为ExtendMenu,而我们的词霸扩展插件需要放入这个ExtendMenu中作为其子插件,则Container的值为 Toolbar.ExtendMenu。


由于加载器需要维护一个统一的拼合后的插件树结构,Mussel引入了一个ContainerNode节点的类型,这个类与AddinNode不同,AddinNode只是针对所在的插件来描述结构,而ContainerNode是所有Addin拼合后的结果。我们分别看看这些相关联类型的类图:

 

接下来,我们写个测试程序来测试一下Mussel的插件树,在Mussel.Core程序集中,有一个默认提供的插件“BasicFormatter”,这是一个格式化器,我们先不用关心这个插件如何用及干什么用的,我们先拿它来测试一下Mussel的插件树,通过装载器装载后,输出各种信息,让我们对Mussel的插件树结构有一个更感性的认识。


主程序的代码


第一个插件的配置文件(Core.addin)

第二个插件的配置文件(Data.addin)

第三个插件的配置文件(Data1.addin)


在这个程序中,我们放了三个配置文件给Mussel加载,并且这三个插件配置文件中都有相应的关联信息,我们来看看输出的结果

输出的结果

程序输出的结果

    点击下载此文件