开放工厂所有插件基于OSGi.NET面向服务插件框架构建。该框架是国际上第一个完整迁移了OSGi R4规范的OSGi.NET框架,提供了动态模块化、面向服务和模块扩展三大功能,支持WinForm桌面应用、WPF桌面应用、ASP.NET Web应用、ASP.NET MVC应用、Silverlight RIA应用、手机应用等任意.NET应用环境
1.1 开放工厂架构
开放工厂由OSGi.NET插件框架和插件仓库组成
1.2 开放工厂具有六方面的价值
2.1 插件和插件运行时
在OSGi.NET插件框架中,插件即Bundle,它具备物理隔离、热插拔和动态特性。每一个插件都是完全可复用的,可以被动态的安装、启动、停止、卸载或更新。插件运行时即BundleRuntime,则是插件的运行容器,它负责从插件目录中加载和启动插件。
2.2 面向服务
在OSGi.NET插件框架中,插件具备高内聚、低耦合特性,也就是说插件间耦合度非常低。服务即Service,是插件通讯的方式。在这里,“服务=接口 + 实现”。接口是服务的契约(即接口),服务提供商实现了服务的接口并将服务注册到服务总线,服务消费者则通过服务契约从服务总线搜索服务并绑定使用。这里,服务是动态,可以被动态注册、卸载和更新,一个服务契约也可能有多个服务实现。
2.3 插件扩展
在OSGi.NET插件框架,插件具备可扩展性,可以在不变更插件代码情况下,更改或者扩展插件的行为。这个扩展机制是通过一对基于XML格式的“扩展点 + 扩展”来实现的。一个插件可以通过定义“扩展点”来实现可扩展,而其它插件则通过定义对应的“扩展”来注册/更新功能。扩展/扩展点在插件启动时注册到插件运行时,相反,在卸载时,则从插件运行时卸载。
2.4 片段插件
在OSGi.NET,有一种特殊的插件,称为片段插件,即Fragment Bundle。片段插件相当于子插件,其作用是为了扩充其它插件的类型空间、扩展信息。除了片段插件的插件,都是宿主插件(Host Bundle)。与宿主插件不同的是,片段插件不能被启动、停止,没有类加载器,不允许从片段插件加载类型。当宿主插件被启动后,片段插件会自动附加到宿主插件,即将片段插件的类型空间、扩展信息合并到宿主插件。
3.1 开放工厂原理概述
插件生命周期顺序:
7(更新升级内核)->5,6(被启动的插件调用插件管理服务来更新升级插件)->1(获取页面流服务,入口点插件,进入主界面) -> 4,6(插件中心插件调用插件管理服务,更新升级插件)->2,3(远程控制)
当插件程序运行后,它首先调用iOpenWorks启动程序来检测OSGi.NET插件框架等内核文件版本并下载更新,接着启动插件运行时, 从Plugins目录中加载并启动插件。在这里,iOpenWorks启动程序将调用开放工厂平台的插件仓库OpenAPI检查是否有新版本的内核并从 仓库中下载最新版本的文件(如原理图的箭头7所示)。
在启动插件过程中,如果应用程序下载安装了自动更新插件,该插件会调用插件管理服务来检查插件仓库更新情况,并自动下载最新版本 的更新包,等重新启动应用程序时,执行自动更新。在这里,插件管理服务将调用开放工厂平台的插件仓库OpenAPI来获取插件仓库的新插件 和新版本的插件并利用OpenAPI进行下载安装或升级插件(如原理图的箭头5、6所示)。
插件运行时启动完成后,主程序从运行时获取页面流服务,获取入口点并运行入口插件的程序,进入主界面或者插件中心插件(如原理图的箭头1所示)。
插件中心插件也将调用插件管理服务,获取开放工厂插件仓库的新插件和插件的最新版本,当点击下载插件时,利用插件管理服务从插件仓库 下载安装或升级插件(如原理图的箭头4、6所示)。
此外,当插件运行时启动完成后,远程管理服务插件利用WebService服务包装器将OSGi.NET内核管理功能暴露成Web服务,这样OSGi.NET 插件SDK的远程管理控制台运行起来后,便可以调用该Web服务实现内核插件、服务浏览以及插件启动、停止、卸载和安装操作,方便插件程序的 调试(如原理图的箭头2、3所示)。
iOpenWorks开放工厂平台主要由插件仓库和插件仓库OpenAPI组成。插件仓库实现插件的版本管理、OSGi.NET内核文件版本管理、SDK及客户端 管理,而插件仓库OpenAPI则向外暴露了插件及其版本信息、内核文件及其版本信息从而为客户端提供内核及插件的自动升级支持。
OSGi.NET插件SDK由开发者安装,向开发者提供了OSGi.NET插件框架、OSGi.NET Web扩展、iOpenWorks启动程序这三个开发程序集,此外,还提供了插件项目模板、 远程管理控制台(用于调试用,可以查看OSGi.NET内核情况)、文档、示例。开发者使用OSGi.NET插件SDK的项目模板来创建WinForm或者Web插件 应用程序时,这个模板默认实现了:
4.1 插件
在OSGi.NET插件框架中,插件是一个具备物理隔离性、完全重用的功能模块。在这里“插件=Manifest.xml + 类 + 资源”,Manifest.xml是插件的描述文件,位于插件目录的根目录下;类即插件的类型空间,由插件自身的程序集和依赖的插件/依赖的程序集组成,资源类似与类,由插件本身的资源和依赖的资源组成。
4.2 插件目录
插件由Manifest.xml插件清单文件、程序集、资源组成,程序集和资源位于插件根目录或者子目录下。其标准目录结构如下。
4.3 插件类加载
在OSGi.NET插件框架中,插件拥有独立的目录结构,具备物理隔离性。相应地,每一个插件有独立的类型空间,这个类型空间由插件程序集、插件依赖的程序集、片段插件程序集和片段插件依赖的程序集组成。插件的类型是由插件类加载器来加载的。
当你在插件中使用一个类型创建一个对象时,比如MyClassInBundle myClass = new MyClassInBundle(),插件类加载器会按照上面的顺序搜索需要加载的MyClassInBundle类型。与此同时,你也可以通过调用插件对象的LoadClass方法(IBundle.LoadClass)从插件类型空间中动态加载一个类型
4.4 插件生命周期
在OSGi.NET插件框架中,插件具有生命周期。插件生命周期状态有:Installed、Resolved、Active、Uninstalled四个可见状态和Starting、Stopping两个临时状态。其中,Installed表示插件已经安装;Resolved表示插件依赖的程序集或者依赖的插件已经满足,这个插件可以被正常启动;Active则表示插件已经被成功启动;Uninstalled表示插件已经被卸载。Starting是一个过渡状态,当启动插件时,如果插件使用了晚激活策略,则插件在注册扩展信息、服务信息之后,直接返回,不会执行激活器的Start方法,这个方法会推迟到第一次从这个插件加载类型时调用并进入Active状态;反之,如果没有使用晚激活策略,插件会调用激活器Start方法并进入Active状态。在启动过程,如果出现异常,则插件会自动转回Resolved状态。Stopping是另一个临时状态,在停止插件时,首先进入该状态,然后调用激活器的Stop方法后进入Resolved状态。
4.5 插件运行时和插件启动过程
插件框架启动时,首先从插件目录中发现并加载所有的插件;然后,对插件进行依赖解析,判断插件依赖的程序集和依赖的插件是否满足;接着,按照启动级别顺序启动所需的插件;一旦插件启动完成,则插件框架便完成启动。
在插件启动过程中,将按照创建插件上下文、注册扩展点/扩展信息、注册服务信息、创建插件激活器并调用Start方法的顺序完成一个插件的启动过程。如果插件实现的晚激活,则推迟最后一步的执行,直到第一次从插件加载类型;如果插件没有定义激活器,则忽略最后一步。
5.1 插件运行时BundleRuntime
插件运行时BundleRuntime代表插件框架内核对象,它是所有插件的运行容器。 在示例中,控制台主程序在Program的Main函数中,通过创建BundleRuntime对象并调用其 Start方法来启动插件框架内核。当Start方法调用完成后,BundleRuntime对象将从插件目 录中加载插件并启动插件。
5.2 插件
插件也称为Bundle,从OSGi.NET规范上讲,“插件=Manifest.xml + 类 + 资源”。其中, Manifest.xml即插件清单文件,用于描述插件的基本信息、类型信息和扩展信息; 插件具备隔离的类型空间,由插件本身的程序集和依赖的插件的程序集组成; 插件拥有自己的资源,存放在私有的文件夹。
在定义一个插件时,您只需要关注三个非常重要的接口,分别是:插件激活器IBundleActivator、 插件IBundle和插件上下文IBundleContext。其中,插件激活器由开发人员自己定义;而插件IBundle和插件上下文IBundleContext则由插件内核创建, 你可以在插件激活器获取中获取到这两个对象
5.3 插件清单Mainfest.xml
插件清单文件(Manifest.xml)位于模块标准目录结构的根目录之下,它定义了模块的基本信息、模块激活信息、模块类加载相关的运行时信息、服务定义信息、模块扩展定义信息以及模块详细信息。
以上清单文件定义了该模块的一个本地程序集“bin\ShellPlugin.dll”,该程序集位置相对于模块的根目录,当然,你也可以指定一个绝对目录。模块还定义了一个激活器和扩展点。
5.3 IBundleActivator
IBundleActivator表示插件激活器,是插件的入口和出口,用于在插件启动或停止时执行相关操作。
插件激活器通过Manifest.xml的Activator节点配置,当插件被启动时插件激活器的Start方法被调用, 当停止时Stop方法被调用。
在插件激活器的Start/Stop方法的context参数,即插件上下文IBundleContext对象,通过IBundleContext 您还可以获取对应的插件IBundle实例。
5.4 IBundle
IBundle表示由内核创建的一个插件,一般而言,“Bundle=Manifest.xml + 类 + 资源”。 插件对象向您暴露了以下功能:
5.5 IBundleContext
IBundleContext表示插件上下文,实现了对插件框架的反射,通过模块激活器IBundleActivator的 Start/Stop方法的参数获取该对象。 插件上下文向您暴露了以下功能:
UIOSP 官网:http://www.iopenworks.com/
OSGI.NET 官网:http://osgi.codeplex.com/
参考资料:http://www.cnblogs.com/zhaojudi/archive/2013/02/26/2933788.html
http://www.cnblogs.com/shalahu/archive/2013/02/21/2921306.html
示例源码: http://osgi.codeplex.com/SourceControl/latest