- 问题
不是所有的应用程序组件需要相同的可见性与生命周期,一个智能客户端应用程序管理着许多不同的组件的实例,比如 Services (服务), Event Topics (事件主题),Commands (命令),Work Spaces (工作区),还有 UI Extension Elements (界面扩展元素),这些实例联系紧密,它们一起被创建,也一起被销毁。这些关联的组件实例能够互相访问,但是它们不能访问不被关联的组件。
- 解决方案
将相互关联的组件放入容器并形成一个层次结构,这个容器是一个能够封装并跟踪多个组件的特殊对象,在这里,“封装”这个术语指的是逻辑上的包含。
这个容器的层次结构能够控制应用程序组件的可见性与生命周期,参考以下图示中的示例容器层次结构。在这个图示中,容器 C1 是层次结构的根结点,同时它是 C2 的上层结点,容器 C2 是 C3 的上层结点,容器 C1 封装了组件 a 和 b,容器 C2 封装了组件 c, d 和 e,容器 C3 封装了组件 f 和 g。
Figure 1
Container hierarchy
可以向一个容器中添加或删除组件。当一个容器被删除后,所有它的组件也一起被删除,同时删除操作对容器层次结构也有级联效应,例如,如果容器 C2被删除,容器 C3也会自动删除,C2 与 C3的组件 c, d, e, f 和 g 也全部被删除。
一个组件能够访问位于同一容器中的其他组件,要访问其他容器中的组件,你可以通过 Parent 和 WorkItems 属性来访问整个容器层次结构。然而,有另外一种推荐的做法就是在不同容器的组件之间使用事件,当你声明了事件,同时可以指定其可见性,以下为事件可见性的三种范围:
1. 容器级别,事件仅对同一容器中的组件可见。
2. 容器及其所有子容器级别,事件对容器及以下层级结构中的所有组件可见。
3. 全局级别,事件对容器层级结构中的所有组件可见。
- 示例
Smart Client Software Factory中Composite UI Application Block 的 WorkItem (工作项) 就是一个容器。WorkItem 有一个叫Items 的集合属性,Items 集合包含了多个子 WorkItem 容器。理论上,一个Composite UI Application Block的智能客户端应用就是一个 WorkItem 的层次结构,层次中的根结点 WorkItem 是由Composite UI Application Block 框架在Shell Application (外壳应用程序) 启动时创建的,当一个 Module (模块) 被加载到应用程序,框架将根结点 WorkItem 传递给这个 Module,它也有自己的 WorkItem,并把它加到根结点 WorkItem 之下,这样就表示这个 Module 的 WorkItem 是根结点 WorkItem 的子结点。
关于这个模式的具体示例,请参见Smart Client Software Factory参考实现示例中的 ShellApplication 类和 Module 类。根结点 WorkItem 是由ShellApplication 类的 RootWorkItem 属性展现的,Module 类的 Load 方法负责创建一个新的 WorkItem 实例(在示例中表示为 ControlledWorkItem),并将它加到根结点 WorkItem 容器中。