SharpDevelop插件系统与UIP(UserInterfaceProcess)介绍

插件及UIP配置说明
一,插件系统

1.1,插件系统介绍
   插件系统是为了应用程序扩展方便而建立的扩展接口,它把扩展对象抽象化,利用xml文件的配置,来达到组合并使用用户定义的功能的目的。插件系统全部以代码子(Codon)为基础,
通过Xml文件来配置代码子,插件系统在运行时来组合对象并达到利用用户功能的目的,可以简单地把代码子看成是一个对象的XMl序列化,此外对象的生成是由代码子自身完成的,只有代码子能识别代码子,比如代码子的嵌套,也就是说只有代码子自身能够识别其子代码子。在这里要说明一点,代码子对象和代码子运行时对象是两个不同的概念,代码子对象是插件树结构的组成部分,而代码子运行时对象则是通过代码子组合后的对象。如果没有特别说明,在本文档的以下部分都将使用这两个术语。由于插件系统有且只有一棵树,故而在整个插件系统中使用了单件模式,AddInTreeSingleton类就是其实现形式。

1.2,插件配置文件分析并建立自己的代码子对象
插件系统是以.addin文件为结尾的文件,其结构大致如下:
<?xml version="1.0" encoding="GB2312"?>
<AddIn author="Spider"
       copyright="Copyright@2005"
       description="Spider module"
       name="Spider.Application.CTS"
       url="http://www.13cn.com"
       version="1.0.0"
      >
       <Runtime>
       <Import assembly="../bin/Spider.Application.CTS.BaseInfo.View.dll"/>
       <Import assembly="../bin/Spider.Application.CTS.BaseInfo.Controller.dll"/>
       <Import assembly="../bin/Spider.Framework.DevExHost.dll"/>
       </Runtime>
       <Extension path="/Workspace/FunctionalityDataItems">
<FunctionalityDataItem id="CTS.BaseInfo.BM_Otherh"
 loader="Spider.Framework.DevExHost.Functionalitys.DevViewFunctionalityLoader"
 startupModel="DirectView"
 caption="其他资料"
 beginGroup="false"
 view="CTS.BaseInfo.View.BM_OtherhList"
/>
       </Extension>
</AddIn>

从整个插件系统的结构上来看,配置文件可以看成是插件系统各个对象的xml串行化,
AddIn对应AddIn对象
Runtime     对应AddIn.Runtime

Extension对应AddIn.Extension

。。。。。

functionality就是代码子对象,以下就是建立代码子对象的基本步骤:
1,代码子对象的基类是ICodon和AbstractCodon,所有的代码子对象都应该从这两个对象派生,建议从AbstractCodon派生,这样可以省去很多麻烦,以下是其属性的说明:

id 代码子的唯一标识,注意所有的代码子ID号在同一路径下必须唯一
class代码子所关联的行为对象,注意这个对象必须从ICommand或这        AbstractCommand派生,因为代码子始终执行ICommand中的Run方法,
菜单中的点击动作就是这个原理,具体可以参见Spider.Framework.Host.AddIn.Codon和Command的代码。
insertafter 把代码子插入在制定的代码子之后
insertbefore 与上相反

2,建立自定义的代码子属性,注意所有的代码子属性如果想要被配置文件识别,必须添加扩展  属性声明,以下是要用到的扩展属性:
 CodonNameAttribute 代码子的名称
 XmlMemberArrayAttribute一个字符串数组对象
 XmlMemberAttributeAttribute简单的字符对象

例如下面要建立的代码子:
 [CodonName("Test")]
 public class TestCodon:AbstractCodon{
[XmlMemberAttribute("name")]
private string _name=null;

public string Name{
get{
return _name;
   }
set{
_name=value;
  }
}
}
3,重写BuildItem方法,完成上面的例子
 [CodonName("Test")]
 public class TestCodon:AbstractCodon{
[XmlMemberAttribute("name")]
private string _name=null;

public string Name{
get{
return _name;
   }
set{
_name=value;
  }
}

public override object BuildItem(object owner, ArrayList subItems, Spider.Framework.Host.AddIns.Conditions.ConditionCollection conditions){

object result=new object();
return result;
}
}

4,建立关联的Command对象,以上说了所有的Command对象必须从ICommand或AbstractCommand派生,当然最好从AbstractCommand派生,以下是一个例子:
public class TestCommand:AbstractCommand{
public override object Owner{
get{
return null;
   }
set{
;
   }
}

public override Run(){
}
}
1.2,插件系统的启动过程,
1,插件系统去搜索用户的插件定义目录,用户定义的目录是在App.conf文件中定义的,此外如  果找不到用户定义的目录,插件系统会使用其自身默认的插件目录,具体可以参见AddInTreeSingleton类,里面有其完整的实现。

2,建立插件树并初始化树。插件系统是以插件文件中Extension节点的PATH路径来识别每个插件树节点,你可以在不同的插件里面来扩展和定义这个路径下面的节点。在这一步中,插件系统会加载所有的插件文件,并根据节点路径生成完整的插件树,注意在生成插件树的过程中代码子运行时对象是不会建立的,仅仅是建立了代码子对象,运行时对象是在用户组合代码子功能的时候才会创建。关于这部分,情自行参见AddInTreeSingleton类里面的代码实现。

3,在建立好插件树之后,就是应用程序来利用代码子组合应用程序的时候。一般来讲插件系统都是通过服务(Service)来管理并组合这些代码子的。关于服务将会在下文中讲到。要建立代码子对象首先要获取给定路径下面的节点,这个步骤是通过AddInTreeSingleton.AddInTree.GetTreeNode这个方法来实现的,它返回一个IAddInTreeNode对象,显然这不是我们想要的,要想利用代码子运行时对象,必须通过IAddInTreeNode.BuildItem或IAddInTreeNode.BuildItems方法来实现,其中前一个方法只会建立一个代码子运行时对象并返回一个Object对象,而后一个方法会建立改路径下面的所有代码子对象并返回一个ArrayList的数组。

4,在第3步中已经看到了,在建立好插件系统后,我们就可以得到任意节点下面所有的代码子运行时对象,公司的应用程序里面整个插件系统的组合都是在DevExHost工程里面完成的,
下面就来讲一下DevExHost工程的结构。

目录组织:
Codons通用代码子对象
Commands代码子运行时接受用户的动作后所做出的反映
Functionalitys功能子对象
Services服务对象
SpiderDevExGui程序对DevExpress控件的封装
UIPUserInterface对象集合

其他目录都是和代码子相关的对象,请自行参见代码,这里重点介绍的SpiderDevExGui目录下Workbench目录下的DevExWorkbenchMainForm窗体对象,因为基本上所有加载的动作都是在这个类里面完成的,请自行参见其代码,那里注释的很清楚了。

1.3,服务对象(Service)
其实Service对象也是建立在代码子的基础之上,主要是这些对象在运行时就已经在高速缓存里面存在,以供快速调用,建立一个Service对象和建立代码子对象没什么区别,但是有一点必须注意,普通的代码子对象可以不必指定class属性,但是Service对象的代码子必须指定
class属性,此外所有的服务对象都是通过ServiceManager类来管理的,要添加一个服务对象请使用ServiceManager.Services.Add(serviceObject)方法,要获取一个服务对象请使用ServiceManager.Services.GetService(Type serviceType)方法,要了解更详细的信息请自行参见
Spider.Framework.Host.Services里面的代码。

1.4,功能子对象(Functionality)
    其实功能子对象很简单,在插件系统中,每一个功能都要定义属性及class对象,各个对象之间是不能重复使用的,功能子要做的就是把代码子所有需要的属性通过其来封装,以后在其他的代码子中就能重复调用,要了解更详细的信息,请自行参见Spider.Application.Common.AppFunctionality工程,那里代码注释的已经很清楚了。


二,UIP(User interface processer)说明

2.1,什么UIP
   从UIP的名字就可以看出来,它主要是把用户从事件到业务处理代码分离开来,更好第实  现MVC的一个功能性应用程序,具体的说明请参见微软的UIP说明文档。

2.2,UIP的运行方式
UIP是通过Xml文件来配置的,所有对象配置及对象的组合都是在Configuration目录下的对象来完成的,最重要的几个配置有ControllerSettings,ViewSettings,ViewManagerSettings等,其中UIPConfiguration类是UIP的入口对象,详细的请自行参见代码。

首先UIP读取配置信息并建立配置对象的运行时对象,所有的UIP必须先启动,这个是通过UIPManager里面的startTask之类的方法来启动,其中在公司的应用程序里面UIP的启动是在用户成功登陆后启动的,详见Spider.Framework.DevExHost里面的登录窗体里面的代码,
用户到另一个窗体的跳转是通过Navigator对象完成的,所有的事件执行后的动作都是在Controller类里面完成的,窗体的显示是通过ViewMananger来显示的,当然你也可以建立自己的Controller,Navigator,ViewManager类来实现自定义的导航,但必须从相关的基类派生,其他的这里就不在多说了,详见微软的UIP说明文档。

2.3,公司应用程序的UIP配置
UIP的配置本来是通过App.conf配置文件来配置的,但是为了和系统的插件系统保持兼容,故而在公司的架构中UIP的配置是通过代码子来完成的,其中在Spider.Framework.UIProcess.Codons下面有每个配置对象的代码子封装。

从配置文件到代码子对象的实现,其实原理很简单,只不过是在UIP加载的时候做了手脚,过去UIP是从配置文件里面读取并创建对象并添加到相关对象集合里面去的,现在则是通过插件来建立对象并用自定义的方法来添加到UIP相关对象集合里面去。所有的处理动作都放在了Spider.Framework.UIProcess.UIPConfiguration类中执行的,因为它是整个UIP的入口对象,处理代码子的代码请自行参见代码。

2.4,UIP重点配置对象的说明

ViewSettings

id标识,即作为代码子的标识也对应于UIP里面的ViewName

layoutManager布局管理器

stayOpen 是否一直处于打开状态,如果设置了此属性为真,那么这个窗体会在程序运行期间一直存在,当你跳转到其他窗体时它会自动隐藏,离开其它窗口后,它会自动恢复其状态。

openModal标识窗体是否时有模式打开,其实也就对应窗体里面的ShowDialog()方法

floatable标识窗体是否是一个浮动窗体

canHaveFloatingWidows标识窗体是否能具有浮动的窗体,也就是说该窗体是否是其他窗体的容器
ContainerViewSettings
view对应的ViewSettings对象的名字
ViewContainer其父窗体


ViewContainerSettings
mainView对应的主窗体的名字,要作为父窗体的窗体


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值