使用 SailingEase WinForm 框架构建复合式应用程序(插件式应用程序)
2012-05-13 01:16 pptp998666 阅读(5016) 评论(0) 编辑 收藏 举报SailingEase WinForm Framework WinForm开发框架开发手册:http://docs.shengxunwei.com/Home/Browser/sewinformfw/
对于一些较小的项目,具备一定经验的开发人员应该能够设计和构建出便于进行维护和扩展的应用程序。但是,随着功能模块数量(以及开发维护这些部件的人员)的不断增加,对项目实施控制的难度开始呈指数级增长。
SailingEase WinForm 框架为您提供了针对此问题提出的解决方案。在本文中,将对基于SailingEase WinForm 框架的复合应用程序的定义进行解释,并简要说明如何才能构建一个基于 SailingEase WinForm 框架功能的复合应用程序。
传统的单一应用程序
传统的单一应用程序每个控件都紧密耦合在一起,UI 中存在大量用于协调各个部分的逻辑。控件之间还存在着相互依赖关系。
由于存在这些依赖关系,因此无法通过某种简单的方法将应用程序分解成可在其中分别开发各个不同部分的窗体。虽然可以将所有用户控件都放在一个单独的程序集中以提高可维护性,但这种做法只是将问题从主应用程序转移到了控件程序集,治标不治本。在这种模型中,进行重大更改或引入新功能都非常困难。
基于 SailingEase WinForm 框架的复合应用程序(插件式应用程序)
基于 SailingEase WinForm 框架的复合应用程序由运行时动态发现和构成的松散耦合模块组成。模块包含代表系统的不同垂直片段的可视和非可视组件。可视组件(视图)被组合在一个常规外壳中,可用作应用程序所有内容的宿主。复合应用程序可提供各种服务,将这些模块级组件结合在一起。模块可提供与应用程序的特定功能相关的其他服务。
从较高的层次来看,复合应用程序是“复合视图”设计模式的实现,此模式可描述包含子项的视图的递归 UI 结构,这些子项本身也是视图。这些视图然后通过某种机制组合起来 — 通常是在运行时而非设计时静态组合。
模块会影响在其中创建主复合视图(也称为外壳)的视图。模块永远不会相互直接引用,也不会直接引用外壳。相反,它们会利用服务在彼此之间以及与外壳之间进行通信,以响应用户操作。
使用模块来组成系统有很多好处。模块可聚合来自同一应用程序中不同后端系统的数据。此外,系统可随着时间的推移更加方便地发展演变。在系统需求发生变化而需要向系统中添加新模块时,与非模块化系统相比,模块化系统面临的冲突要少很多。而且还可以对现有模块进行独立性更强的改进,从而改善可测试性。最后,模块可由不同的团队开发、测试和维护。
一个典型的基于 SailingEase WinForm框架的应用程序
详询QQ:279060597
创建基于 SailingEase WinForm 框架的应用程序
引导程序和容器
使用 SailingEase WinForm 框架构建复合应用程序时,首先必须初始化几个核心复合服务。这就引入了引导程序。它可以执行发生复合所需的全部功能。在许多方面,它都类似于应用程序的 Main 方法。
对于容器,指的是控制反转 (IoC) 容器/依赖关系注入 (DI) 容器。容器在应用程序中起着关键作用。容器存储着应用程序中使用的所有应用程序服务。它负责在需要的位置注入这些服务。
在配置容器的同时,还会自动注册几个核心服务(如事件聚合器),基本的引导程序允许您覆盖其中的任何服务。例如,自动注册 ImoduleLoader 服务。如果在引导程序中覆盖 ConfigureContainer 方法,即可注册自己的模块加载程序。
模块的加载
在引导程序中,通过覆盖方法 GetModuleCatalog 即可加载所需的模块,除了通过 ModuleCatalog 的 AddModule 方法来加载模块之外,可以在此实现其它任何所需的模块加载方式。
定义并实现一个模块
在基于 SailingEase WinForm框架的应用程序中,模块是复合应用程序的分离单位,可将其部署为单独的程序集(尽管并非必需)。模块包含了大部分的功能。
这是一个基于 SailingEase WinForm框架的应用中的一个模块,StartPageModule.cs是实现 IModule 接口的类。此接口仅包含一个方法,称为 Initialize。如果把引导程序看作应用程序的 Main 方法,那么此处的 Initialize 方法就是模块的 Main。
在该模块的构造函数中,我们取得 IUnityContainer 容器,事件聚合器 IEventAggregator ,以及工作区服务 IWorkbenchService。
IUnityContainer,IEventAggregator和IWorkbenchService它们究竟从何而来?我是否要将逻辑硬编码到模块的初始化代码中?
答案是“否”。加载模块时,SailingEase WinForm框架自动将模块需要的服务从容器中解析出来,注入到模块的构造函数中,如果我们需要在模块初始化时获得其它服务,只需在构造函数中直接加入参数即可。
在该模块的 Initialize 方法中,我们做了两件事:注册导航项到应用程序的外壳(主窗口)中,订阅应用程序中的事件。
在不同的模块间发布/订阅事件
SailingEase WinForm 框架为您提供了事件聚合服务,在传统的单一应用中,不同功能点之间的事件订阅是直接的引用与依赖关系,而SailingEase WinForm 框架通过事件聚合服务,使得事件的订阅者,与发布者完全解耦合,不存在任何引用与依赖关系。
传统的应用程序事件发布订阅:
功能A发布事件 ProjectOpenedEvent ,功能B订阅此事件时,必须在编码过程中依赖,引用功能A的程序集或者类。
基于 SailingEase WinForm 框架的事件发布订阅:
模块B获得事件聚合服务,向事件聚合器订阅事件 ProjectOpenedEvent,当有其它事件发布者,如模块A,向事件聚合器发布事件 ProjectOpenedEvent时,模块B将得到通知从而执行相关代码。
模块A与模块B,或更多的此事件订阅、发布者,不存在任何依赖,引用关系,它们通过事件聚合服务发布,订阅事件。
例如我们上文中的 StartPageModule 订阅了两个事件,ApplicationRunEvent 和 ProjectOpenedEvent。
我们的 StartPageModule 无需关心谁是事件 ApplicationRunEvent 和 ProjectOpenedEvent 的发布者,也无需关系发布者将在什么情况下,什么时间发布这两个事件,StartPageModule 只需做好响应这两个事件的准备即可。
而我们的事件发布者,也无需关心谁是事件的订阅者,只需在应该发布事件的时候,向事件聚合器发布对应的事件即可。
下面的代码发布了事件 ApplicationRunEvent。
通过事件聚合机制,模块间的事件发布,响应实现了完全的解耦合,模块与模块间不存在任何引用,依赖的关系。即使将某个事件的订阅者模块或发布者模块暂时的移出系统,其它模块都不会受到影响。
通过服务在不同的模块间交互数据或调用功能
在过去单一式应用程序中,当不同的功能点间需要交互数据或存在功能调用时,通常在编码时就将它们放在一起,有经验的程序员或许会将不同的功能点放在不同的程序集中,但依然避免不了程序集间互相引用所造成的高度耦合与依赖。
在 SailingEase WinForm 框架中,通过服务的概念来解决模块间的互操作问题,使模块间不存在任何依赖与引用。
通过一个简单的例子就能了解,例如我们的模块A提供了客户的基本信息管理功能,而模块B专门用于处理与客户的联系记录。如何在模块A中需要列出指定客户的联系记录?
我们为客户联系记录管理模块(模块B)设计一个服务接口 ICustomerContactService,我们将该接口定义在一个所有模块都已知的基础程序集 Infrastructure 中,然后我们在模块B中实现此接口,实现接口中定义的用于提供联系记录信息的方法,并将实现后的服务注册到 SailingEase WinForm 框架的服务容器中。
模块A在需要列出客户的联系记录信息时,只需从服务容器中取出 ICustomerContactService,即可通过该接口调用其所提供的方法获取信息,而不必关系接口的实现者与提供者是谁。
SailingEase WinForm 框架为您实现了许多用于开发基于.NET 平台的 Windows应用程序所需的服务,如多文档窗口管理,上下文菜单管理,系统环境相关的服务等等。基于这些服务,您将轻易获得质量可靠,扩展性强,低耦合度可配置化的专业Windows应用程序。
SailingEase WinForm 框架提供完整的源代码,代码风格优秀,带有详细的注释和说明,在使用 SailingEase Winform框架的过程中,我们提供全程指引与技术支持。
另请参阅:
使用 SailingEase WinForm 框架构建复合式应用程序(插件式应用程序)
未完待续,敬请期待……
Email:cao.silhouette@gmail.com
QQ:279060597
Windows开发框架,WinForm开发框架,.NET开发框架