SailingEase WinForm Framework WinForm开发框架开发手册:http://docs.shengxunwei.com/Home/Browser/sewinformfw/
本系列文章以 SailingEase WinForm Framework 为基础进行设计并实现,但其中的设计理念及方法,亦适用于任何类型的客户端应用程序的设计与开发。
目录:
http://www.cnblogs.com/sheng_chao/p/6084144.html
SailingEase WinForm Framework
其实这是从 IDE 项目中提取出来的一个纯开发框架,它没有用户管理、权限管理之类的现成功能,而是提供纯开发角度的开发框架,概括来说提供了以下几方面的功能:
a.宿主程序(壳)与功能模块(插件)的加载、调度、通信等实现;
b.不同插件之间在完全接耦合的基础上,同步/异步调用、状态响应等机制的实现;
c.插件之间在代码层面完全没有互相引用关系,可以实现在缺少任意插件的情况下启动应用,即使他们在UI层有交集;
d.支持模块间的依存关系定义;
d.事件聚合器,用于在完全解耦的条件下,发布及订阅事件;
d.宿主程序提供了统一的主菜单及右键菜单的注册/吊销/状态控制机制;
e.宿主程序提供了统一的窗口调度/加载/销毁功能;
f.宿主程序提供了统一的日志记录、异常捕获,Web页面互操作等功能;
g.基于 GDI+ 自行实现的控件包,提供了高度的可扩展性;
h.基于zip格式的文件包管理器(基于zip的自定义文件格式,读取或写入指定的流);
i.对http、xml、磁盘io、反射、加解密等操作的增强与封装;
j.其它……
第二章节:开始搭建模块化的程序框架
在前文中,我们概述了基于 SailingEase Winform Framework 的客户端应用程序的架构设计,和模块化应用程序的设计理念,本章节将具体阐述模块化应用程序的搭建方法。
应用程序的结构
我们先从视图的角度,直观的分解一个客户端应用程序的框架:
关于模块化的具体阐述,请参考前文:http://www.cnblogs.com/sheng_chao/p/6072232.html
应用程序宿主(白底部分),提供了主窗口的默认实现,并向功能模块开放各种基础服务,和视图部分紧密相关的有两部分:
1)主菜单/工具栏控制器;
允许各功能模块,向宿主注册主菜单或子菜单项目,或工具栏项目。
通过统一资源标识符的方式提供接口,不需要功能模块提供任何视图层面的实现。过去有一些程序,是直接把子模块的工具栏菜单做成用户控件注册到宿主中,这种方式简单易实现,但是性能和可扩展性,稳定性都比较差。通过统一资源标示符来注册并更新菜单或工具栏的状态,可以从非常细的粒度上解耦UI层,举例来说,我可以实现传统风格的主程序菜单外观,或OFFICE2016风格的侧滑式菜单,都只需要更新主窗口实现即可,模块完全不受影响。从稳定性上来说,模块没有权限参与宿主程序的UI组织,就能在这一方面避免模块本身的问题导致宿主程序崩溃。最后是性能问题,主程序通过较好的代码实现,统一注册并更新菜单或工具栏的状态,可达到最好的性能。这一细节的状态实现,将在后文中详细阐述。
2)工作区管理器,包含视图控制器及调度工具;
我们将主程序的多文档区域,定义为“工作区”。在工作区中,可以呈现许多不同类型的子窗口:
1)以Tab页形式呈现的主文档窗口;
2)以侧滑方式在左侧、右侧、或底部显示的工具窗口;
3)浮动的工具窗口;
工作区服务接口可以帮助模块初始化、检索或者激活已经存在的窗口视图。
什么是窗口调度服务呢?除了不同窗口间的状态切换等,大家可以看一看 Visual Studio,留意他的主菜单和工具栏,会随着文档窗口的切换而有所不同,在入门级的客户端程序开发中,程序员一般会直接在窗口的焦点事件中去显示或隐藏相关联的菜单或工具栏,以主动的方式去操作。
在 SailingEase Winform Framework 中,工作区的窗口调度服务会负责这一行为,根据当前的活动窗口,自动切换关联菜单或工具栏的状态。
相关的几个基本接口设计:
大体上可以望文知义,不再赘述。
框架中实际提供的与工作区相关的接口还有许多,基本的顶层设计包括:
引导程序和容器
使用 SailingEase WinForm Framework 构建应用程序时,首先必须初始化几个核心复合服务。这就引入了引导程序。它可以执行发生复合所需的全部功能。它类似于应用程序的 Main 方法。
对于容器,指的是控制反转 (IoC) 容器/依赖关系注入 (DI) 容器。容器起着关键作用。容器存储着应用程序中使用的所有服务,负责在需要的位置注入这些服务。
在配置容器的同时,还会自动注册几个核心服务(如事件聚合器),引导程序允许覆盖其中的任何服务,如果在引导程序中覆盖 ConfigureContainer 方法,即可注册自己的模块加载程序。
定义并实现一个模块
在基于 SailingEase Winform Framework 的应用程序中,定义一个模块非常简单快速,通常只需要5分钟时间即可把模块的基本框架搭建起来。
这是一个模块定义的示例,StartPageModule.cs 是实现 IModule 接口的类。此接口仅包含一个方法,称为 Initialize。如果把引导程序看作应用程序的 Main 方法,那么此处的 Initialize 方法就是模块的 Main。
在该模块的构造函数中,我们取得 IUnityContainer 容器,事件聚合器 IEventAggregator ,以及工作区服务 IWorkbenchService。
IUnityContainer,IEventAggregator 和 IWorkbenchService 它们究竟从何而来?我是否要将逻辑硬编码到模块的初始化代码中?
答案是“否”。加载模块时,SailingEase Winform Framework 自动将模块需要的服务从容器中解析出来,注入到模块的构造函数中,如果我们需要在模块初始化时获得其它服务,只需在构造函数中直接加入参数即可。
模块的加载
模块的加载,可以通过 App.config 文件的方式配置,也可以通过代码直接配置好,不允许发布版用户自行修改。
我们以在代码中定义模块为例,在引导程序中,通过覆盖方法 GetModuleCatalog 即可加载所需的模块,理论上来说,你可以在此基础上实现任意方法的模块加载逻辑。
将模块加载到宿主中,并启动应用程序之后,即可完成一个最简单的 SailingEase Winform 应用程序。
在下一章节中,我将进一步介绍多个模块的应用程序的构建方法,并阐述他们之间的通信、调度、状态响应的方法。
欢迎加我QQ交流探讨,共同学习:279060597,另外我在南京,有南京的朋友吗?