OSGi.NET 学习笔记 [面向服务架构支持][实例][小结]

Demo 点击下载

目录】- 【面向服务架构支持】-【实例】


  这次我们继续延续“模块化和插件化”那个实例来做展示。


  现有的代码,主程序依赖接口和接口实现的Calculator.Demo1程序集,也就说主程序不仅得知道具体的接口定义,还得知道这个接口具体实现的定义。理论上说,这是面向对象,但也是紧耦合。如果你要替换成另外一个接口实现,你就得重新修改、编译、发布主程序。如何避免这种修改呢?可以通过服务总线来重构它、隔离它、松耦合它。


  好在OSGi.NET的“服务总线”功能是以服务的形式发布的,有两种注册服务方式
  1) 一个是在激活器当中,通过IBundleContext.AddService来添加一个指定接口和此接口实现的一个实例。
  2) 一个是在Manifest.xml当中,通过编辑器添加来完成。
  OSGi.NET 学习笔记 [面向服务架构支持][实例][小结]_第1张图片

  3) 注册完成后,可通过GetService来获取一个指定接口类型的此接口实现的所有实例或者通过GetFirstOrDefaultService来获取一个指定接口类型的此接口实现的第一个或默认实例。这两个方法可以通过激活器里的IBundleContext还有运行时环境BundleRuntime得到。
  OSGi.NET 学习笔记 [面向服务架构支持][实例][小结]_第2张图片


  现在我们来考虑一下,如何添加一个新的接口实现,并实现面向服务。
  1) 现有的接口和接口实现都是在模块Calculator.Demo1里的,我们暂且将之称之为“默认”实现,也就是说如果没有其他实现,我们就调用这个实现逻辑。在Manifest.xml中注册,好处是如果你以后不想要默认实现了,可以简单的处理掉。
  2) 我们再创建一个“控制台插件” Calculator.Demo2,这个插件仅仅是引用Calculator.Demo1,且实现一个相同的接口Calculator.Demo1.ICalculate实现逻辑,只是实现类名不同Calculator.Demo2.Impl.Calculator。并在激活器中注册这个接口的实现的一个实例。
  OSGi.NET 学习笔记 [面向服务架构支持][实例][小结]_第3张图片

  3)因为Calculator.Demo2依赖Calculator.Demo1,存在着依赖和被依赖的关系,所以我们打开Calculator.Demo2的Manifest.xml文件,选择“运行时”、“依赖”、“添加”来打开Calculator.Demo1的Manifest.xml,点击确定即可
    OSGi.NET 学习笔记 [面向服务架构支持][实例][小结]_第4张图片

  4)在主程序中也做相应的修改,简单的拿到所有的接口实现实例,并依次调用。  
  OSGi.NET 学习笔记 [面向服务架构支持][实例][小结]_第5张图片

  5) 运行结果如下
  OSGi.NET 学习笔记 [面向服务架构支持][实例][小结]_第6张图片

  6) 小小的测试一下,我们现在将Calculator.Demo2移出Plugins目录,再来看看执行效果,显然主程序调用了默认实现。
  OSGi.NET 学习笔记 [面向服务架构支持][实例][小结]_第7张图片

 

目录】- 面向服务架构支持】-【小结】
  可以通过测试前后的结果看出,面向服务使得我们的程序逻辑松耦合,即主程序无需也根本不知道一个接口实现Calculator.Demo2.Impl.Calculator的存在,无引用,无依赖。


  如果将来Calculator.Demo2.Impl.Calculator的实现内容变了,对主程序来说不需要任何改变,即可立即运行。这就为“按需所用”提供了非常好的实现方式,比如同一个接口实现了三种不同深度的功能模块,收费方式也不同,则可以按照用户要求,随时替换升级,无需任何额外操作。逻辑的松耦合使得我们更改起来变的容易,物理的模块化和插件化又使我们的部署升级变的容易,比如在线部署,云端部署等。稍后我们还会讲到“热插拔和动态支持”,甚至可能不停机进行部署升级,也就是“即插即用”。


  如果你了解过IoC,可能觉得这里的“服务总线”如果做成IoC容器岂不是更好?是的,OSGi.NET提供的只是一个较轻量级的解决方案,毕竟内核要保持一定的“纯粹”性。官方将在不久的将来,以插件的方式提供一个IoC容器。这个容器说不定会用到我们下一节将提到的“模块可扩展性”。

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