PRISM是美国国家安全局(NSA)收集来自美国各互联网公司的互联网通信程序的代号。该程序也被SIGAD US-984XN所知[4] [5] PRISM根据对Google Inc.等互联网公司的要求收集存储的互联网通信,该互联网公司根据2008年FISA修正法案的第702条将任何符合法院批准的搜索条件的数据移交。国家安全局可以使用这些PRISM请求来定位通过互联网骨干网时加密的通信,将重点放在电信过滤系统早期丢弃的存储数据上,并获取更易于处理的数据其他事情。
PRISM特点PRISM是用来帮助设计和开发一个丰富,灵活,易于维护的WPF和Silverlight应用程序。PRISM库文件实现了一系列重要的设计模式和构架原则,比如关注点分离和松耦合。使用这些PRISM提供的设计模式和能力,可以中设计和实现多个使用各个关联度很低但是却可以轻松整合到一起的组件,并且使用它们组合成为一个系统。
在软件开发过程中,一般认为分模块化地设计软件总是比单一设计要好。然而模块化的设计也是有好坏之别的。它的最主要的两个判断方面就是松耦合和高内聚。耦合和内聚其实是独立的,但是它们经常被用来一起判断模块之间的依赖关系强不强。耦合是越松越好,两个模块耦合越是紧,说明它们的依赖性越是强。只要一个模块改动,另一个模块也会不可避免的要去改动。如果是松耦合的话,就不会因为其他的模块改动而改动了。从内聚来说,是越高越好。如果一个模块有许多不相关的功能,那么它就不是高内聚的,是不好的。例如一个模块可能需要记下日志来帮助日后的分析,但是日志记录并不是这个模块的内容,应该单独把它写入一个logging模块才是正确的选择。
PRISM的关键概念(1)Modules(模块):Modules是一些可以独立开发,测试和(任意)部署的功.能包。通常不同的模块是由不同的团队开发并且维护的。一个典型的PRISM包含了若干个模块。Modules可以用来表示有特定的业务关系的功能(如配置管理器profile management),并且封装了视图,服务,和实现所必要的数据模型。Modules也可以封装一些系统通用模块或服务(如日志,异常管理器)以方便它们在不同系统间复用1。
(2)Module Catalog(模块列表):在一个复杂系统,模块必需在运行时由客户端加载和使用。在PRISM中模块列表用来指定哪些模块应该加载,又应该在什么时候加载,以及用什么顺序加载。模块列表由ModuleManager和
ModuleLoader两个负责远程加载,或者将模块加载到应用程序域和初始化的组件使用。PRISM允许用多种方法定义模块列表,包括使用代码编程,使用XAML定义,或者使用配置文件。也可以根据需要自定义一个模块列表。
(3)Shell:Shell是应用程序加载的第一个模块,它定义了程序的总体布局和结构,它通常不知道在其内的实际应用模块。它通常实现了应用程序的基础服务和框架,大部分程序中功能性的模块都在它的里面运行。它提供了最顶层的的窗口或者可视化元素以便于载入不同的UI模块和功能模块。
(4)View(视图),视图是封装了特定特征和功能区域的用户界面,视图通常和MvvM和MVP设计模式相结合,它提供了一个UI和应用程序表现逻辑或数据间独立的关注点。视图用来封装用户接口和用户交互行为,因此视图可以独立与底层功能进行升级和替换。视图通过数据绑定与View Model.或Presenter层相结合。
(5)View Models和Presenters,View Model是一些封装了应用程序表现逻辑和状态的类。它们是MvⅧ模式的一部分。View Model封装了应用程序中非常多的功能。Presenter与View Model一样也是封闭了应用程序表现逻辑和状态的类,它在MVP模式中被使用。两者都定义了属性,命令和事件,以及哪些控件应该要绑定数据。
(6)ModelS(模型),模型类是数据和应用程序逻辑的封装。它们是MvvM和MVP设计模式中的一部分。模型封装了数据和任何与之相关的验证,以及用来保证数据完整性和一致性的业务逻辑。
(7)Commands(命令),命令是应用程序功能的封装,在某种程序上它们可以与用户UI独立进行测试和定义。它们可以在View Model或者Presenters中被定义成为命令对象或者方法。PRISM提供了DelegateCommond和CompositeCommand类。后者用来表示一组一起调用的命令的集合。
(8)Regions(区域),区域是一个定义在应用程序UI(Shell或者某个视图)中显示哪个视图的逻辑占位符。区域使应用程序可以在不更改代码的情况下切换布局。一些控件可以当成区域,因为他们可以显示其它视图的控件和内容,比如ContentControl,ItemsControl,ListBox,或者TabControl。视图可以通过编程或者自动的方式在区域中显示。PRISM也支持在区域中实现Navigation(导航)。区域可以通过RegionManager放到其它组件中,使用RegionAdapter和RegionBehavior组件来调配显示在特定区域中的视图。
(9)Navigation(导航),导航是应用程序响应用户操作并且显示更换相应UI或者状态的过程。)PRISM支持两种状态的导航:基于状态导航,它是用来实现已经存在的视图的不同场景切换的导航;和视图切换导航,这是在应用程序UI中新视图创建并且代替旧视图的导航。视图切换导航的机制是基于URI的,与PRISM regions一起可以实现一切灵活的导航结构。
(10) EventAggregator(事件聚合器),在一些复杂系统中,组件通常需要通过一些松耦合的方法与其它的组件或服务相交互。为了支持这些,PRISM提供了EventAggregator组件来实现pub—sub事件机制,以此组件可以在不互相引用的前提下发布事件或者订阅其它组件的事件。EventAgrregator通常在不同组件中被定义以用来实现不同模块问的交流。在无需松散耦合的情况下,.NET事件是在组件间建立通信层的最简洁直观的方法。如果不方便将对象与类型和对象引用链接在一起,则应通过事件聚合进行通信。如果使用.NET事件,则必须考虑实施内存管理,当存在短生存期对象订阅静态或长生存期对象事件时尤为如此。如果未删除事件处理程序,由于发布者的引用,订阅者将始终保持活动状态,这将妨碍或延迟订阅者回收垃圾。
(11)Dependency injection container(依赖注入容器),依赖注入(DI)模式在PRISM中普遍使用以保证组件间的依赖可以被管理。依赖注入可以保证组件间的依赖关系可以在运行时被满足,也保证组件的可扩展性和可测性。PRISM的依赖注入是通过Unity,MEF或者其它通过ServiceLocator开发的DI容器。
(12) Service(服务),服务是封装与UI无关功能的集合,比如日志,异常管理器或者数据通道。服务通常在依赖注入窗口中进行注册以使其它可以被其它依赖于它的组件所定位和组建。
(13) Controller(控制器),控制器是用来协调显示在应用程序UI区域中的视图的创建和初始化的类。控制器封装了检测何时应该显示哪个界面的表现逻辑。它使用了PRISM的视图切换导航机制,它是基于URI来创建和切换当前区域中显示视图的导航机制。(应用程序控制器)模式定义了实现这些内容的抽象模型)。
(14) Bootstrapper,Bootstrapper是应用程序用来启动多种PRISM组件和服务的组件。它用来初始化依赖注入容器来注册应用程序层的多种组件和服务。它也用来配置和初始化模块列表,Shell视图和视图模型或者表现界面。
(15) Multi—targeting(多重目标),PRISM所开发的应用程序面向WPF和Silverlight。通过不同的设计模式,比如MVvM和MVP模式,可以将uI和业务逻辑分离开。View Model,Presenter,Model类可以在WPF和Silverlight之间重用。而专门为WPF和专门为Silverlight开发的视图则可以独立封装。PRISM的设计可以让可以根据需求和应用程序场景独立或者全部使用早期的功能或者设计模式。可以使用MVVM模式,模块化,区域,命令,或者事件问的。任何组合而不需要全部一起使用。当然如果想获得松耦合和特殊关注点的完整收益,通常会使用多种PRISM所提供的功能和设计模式。下图显示了一个典型的PRISM应用程序的结构体系以及使PRISM可以运用与多模块复杂系统中的所有功能。大部分PRISM应用程序包含一个Shell,并且在其中定义多个区域以用来显示顶层视图并且发布服务以便其它已载入模块的调用。Shell定义了一个目录用来记录到底模块是在加载的时候被载入或者是在使用时载入。而需要共享的服务和组件则是在程序启动时向Bootstrapper注册。
每个模块都封装了应用程序的一部分功能,并且可以使用表现层分离的设计模式,比如MvⅧ,它了定义的视图,视图模型,模型,和服务组件。当模块被载入时模块定义哪个视图要显示出来,而Shell定义视图显示到哪个区域。在初始化完成后,用户可以通过视图状态导航和视图间导航来可视化的切换区域中的视图或者视图中的不同状态。
PRISM的初始化Bootstrapper是一个负责初始化PRISM应用程序的类。使用Bootstrapper,就可以控制PRISM库中的组件是如何连接到应用程序中的。
PRISM库包含一个可以被继承的Bootstrapper抽象类,它可以使用与任何窗口。该类的大部分方法都是虚方法。可以根据自己的需要重写这些方法。
图1是Bootstrapper所调用的方法顺序,在程序中可以重写其中的方法,达到定制的目的。每一步的详细情况在各小节中有详述。
PRISM提供一些由Bootstrapper继承的类,这些类提供了大部分应用程序所适用的实现。只有初始化并创建Shell这一场景留给自己实现。其中有两类主要继承白Bootstrapper的类,他们分别是UnityBootstrapper和MefBoOtstrapper类,它们分别继承于Unity(Unity Application Block)和
MEF(Managed Extensibility Framework)两种框架。决定在应用程序中使用PRISM,那么就必须做以下决定:
决定使用Unity,MEF,或者其它自定义依赖注入框架。这决定了将使用哪一种Bootstrapper又或者是自定义一个Bootstrapper。
考虑程序中使用的一些特有服务,因为他们需要在容器中注册。
决定使用何种日志服务,比如使用内置的日志服务,或者是自己创建一个。
决定模块的启动顺序:通过详细的代码描述,通过自动检测,配置文件,或者xaml中的属性。
本词条内容贡献者为:
王慧维 - 副研究员 - 西南大学