OSGi.NET 学习笔记 [模块化和插件化][实例]

Demo 点击下载

目录】-【模块化和插件化】-【实例】


  假设我们准备做一个计算器,是的,先从最简单的加减乘除开始。
  1) 先确定一下是命令行显示,.NET 4.5,C#,VS 2012的开发环境;
  2) 第一阶段实现加减乘除功能,用户输入计算公式,回车,返回计算结果;
  3) 其他问题待定。


  OK,先来分析一下如何做。
  1) 逻辑上,简单来说,核心在计算,一种输入,计算和输出的过程。
  2) 其他的就是界面和异常了。


  稍微具体点,
  1) 设计一个接口ICalculate,有返回类型为string的方法Calculate,一个string类型的参数,计算公式。
  2) 一个具体的实现类,继承ICalculate,通过一个DataTable().Compute来直接运算计算公式并返回结果。
  3) 当然有个具体的命令行程序来执行计算公式输入,并调用接口的方法和在界面上输出。


  分析道这里,应该和普通的开发过程大致是一致的,逻辑封装,但对OSGi来说还不够,接下来我们得看看如何物理封装隔离。
  1) 对现在的主程序来说,可能变化的有两个模块,一个是接口,一个是接口的实现。但为了后面的SOA的介绍,我们暂且将接口和接口的实现放在一起,作为单独的一个模块来做物理隔离。


  但在真正开始编码之前,我们需要先简单了解一下OSGi.NET的“模块管理机制”,就是他如何来识别、解析、加载、卸载某个具体模块的。
  1) 首先是OSGi.NET的运行时环境,或者叫插件运行时,他是插件的运行容器,由他来管理所有插件的“生命”,这有点儿像是主板的BIOS,可以启动停止某些组件,比如关闭板载声卡。
  2) 接下来是“生命周期管理”,对于每个模块,在运行时环境里都处在某个特定的状态,默认模块的状态是由运行时来管理的,但通过一定的API调用,我们也可以改变它。理想的状态切换顺序是Installed、Resolved、Starting、Active、Stopping、Uninstalled。其中Resolved可能不太好理解,他其实就是BIOS的“自检”过程,如果模块依赖解析失败就会“Beep报警”。
  3) 还有“依赖解析”,前面说过最理想的状况下,所有模块应该是逻辑和物理都独立的,应该是自依赖,不应该依赖其他任何模块。可实际情况是,大部分时候,我们都必须去依赖。就像现在的主板,板载声卡一般是需要依赖CPU甚至GPU去计算的,就是说一个模块的功能可能依赖另一个模块提供的服务。所以依赖解析就显得非常重要了,他确保了模块之间的依赖关系在当前运行时环境是确实存在的。
  4) 理解这些后,我们来大致推演一下一个模块几个重要的“生命诞生和结束”过程
    a) OSGi.NET运行时启动
    b) 遍历指定路径下所有模块的Manifest.xml文件,得到所有程序集路径和依赖模块等信息
    c) 依赖解析,成功继续,失败停止
    d) 开始启动
    e) 启动成功
    f) 开始停止
    g) 卸载成功
  5) 以上的过程我们可以参与最多的就是开始启动和开始结束,用于前期初始化工作和后期清理扫尾,相当于模块的入口点和出口点,OSGi.NET称之为“激活器”,具体的位置可以在Manifest中定义。
  6) 当然启动时,除了入口点之外,运行时环境启动模块时还为我们做了很多准备工作,比如创建上下文,让其他模块可以访问我们的模块,注册扩展点和扩展,注册服务等等。
  好了,理解完这些,就差不多可以开始动手了,看代码的时候如果有疑问,可以再过来对照参详。

  1) 我们直接使用SDK提供的模板来创建一个“控制台主应用程序”,这里所谓的“主应用”就是启动OSGi运行时环境的入口程序,和普通的.NET无太大区别。
  OSGi.NET 学习笔记 [模块化和插件化][实例]_第1张图片


  2) 创建完成后,我们来看看他的目录结构
  OSGi.NET 学习笔记 [模块化和插件化][实例]_第2张图片
    a) “引用”中包含了最核心的UIShell.OSGi
    b) bin\plugins是默认的OSGi.NET查询路径,且此目录下已经有了两个默认模块,用于和“远程管理工具”交互。
    c) Main函数是程序入口点,在Program.cs文件中,我们可以看到他的主要工作就是启动OSGi.NET运行时环境,BundleRuntime。
    OSGi.NET 学习笔记 [模块化和插件化][实例]_第3张图片


  3) 点击F5可以将它运行起来,当然没有任何逻辑处理,只是输出默认结果
  OSGi.NET 学习笔记 [模块化和插件化][实例]_第4张图片


  4) 我们在点击桌面的“远程管理工具”,输入两个回车,取它的默认值
  OSGi.NET 学习笔记 [模块化和插件化][实例]_第5张图片
    a) 输入list或l,目前将只返回以下结果
    OSGi.NET 学习笔记 [模块化和插件化][实例]_第6张图片
    b) 关于各个值的列的意思和其他命令工具,我们稍后会加以详解。


  5) 好了,先将远程管理工具放在一边,我们继续我们的编程工作。继续通过模板创建一个“控制台插件”,这个“插件”就是一个模块,也就是OSGi叫的Bundle。需要特别注意的是,这个插件的创建路径必须在bin\plugins目录下,否则无法被主应用程序识别和加载。
  OSGi.NET 学习笔记 [模块化和插件化][实例]_第7张图片


  6) 我们继续看看这个插件的目录结构
  OSGi.NET 学习笔记 [模块化和插件化][实例]_第8张图片
    a) “引用”包含了UIShell.OSGi
    b) 这个插件没有入口程序Main,但有一个“激活器”,Activator和它的两个方法Start和Stop,如前面提到的,这就是这个插件的“入口”和“出口”,而这个信息是在Manifest.xml配置指明的,双击Manifest.xml来看看,激活器的值正是Calculator.Demo1.Activator。
    OSGi.NET 学习笔记 [模块化和插件化][实例]_第9张图片
    c) 默认的激活器是什么都不做的,为了显示效果,我们可以让它主动式输出一些信息,例如
    OSGi.NET 学习笔记 [模块化和插件化][实例]_第10张图片
    d) 编译整个工程,点击F5,来看看效果
    OSGi.NET 学习笔记 [模块化和插件化][实例]_第11张图片
    e) 切换到“远程管理工具”,再次输入l,结果如下
    OSGi.NET 学习笔记 [模块化和插件化][实例]_第12张图片
    f) 现在在我们Debug的程序中点击回车,理论上,一闪而过,你应该看到如下结果
    OSGi.NET 学习笔记 [模块化和插件化][实例]_第13张图片
    g) 嗯,到目前为止,一切都OK!推荐再回到前面看看一个模块几个重要的“生命诞生和结束”过程。


  7) 好了,大致跑通了,我们开始真正的实现业务逻辑了,首先在主程序中添加ICalculate接口,并在插件中实现它。具体代码就不贴了,可以自己查看源码。


  8) 来看看主程序如何调用具体的实现的
  OSGi.NET 学习笔记 [模块化和插件化][实例]_第14张图片


  9) 运行结果示例
  OSGi.NET 学习笔记 [模块化和插件化][实例]_第15张图片


  10) OK,虽然比较弱,但差不多能用了。下一步就是结合更多OSGi.NET特性来优化它了。

你可能感兴趣的:(.net)