Blend4发布了,最近就想用研究下Silverligt 4,相信这个版本应该较稳定了。做企业级应用不能不提Prism,这是个不错的企业应用开发指导,新版Prism4支持MEF了,已经发布CTP了。网上中文的资料还真是少,只能看它的帮助文档,看的过程记录下来,加深下记忆。对于正想学习Prism的人希望也有所帮助。本人写作很力很差,写的不好请拍砖!
概览
这一章的内容都是一些整体概述,说明Prism是用来帮助你架建企业级WPF和Silverlight应用程序,它帮助你使用松期满合的组件在一起协作,来生成灵活的客户端程序。这些组件可以独立开发、测试、部署,能够灵活的植入UI的各个区域,从而形成灵活的客户端程序,提高程序的可维护性。如果你是要生成Winform程序,请考虑Smart client soft factory及Composite UI Application block
学习Prism你需要有WPF,Silverliht的开发经验,理解下列概念:数据绑定,资料,命令,路由事件,控件,依赖属性,XAML语言。
Prism的适用场景:
你的应用程序将通过一个整合的界面呈现各种数据(Prism是通过在界面上划分Region,通过将View指定在各个Region来生成UI的)
你的模块之间将会独立开发、测试、部署,有可能是不同的人或团队开发。
你的应用程序将在未来添加更多的功能
对于一些紧急的需求你需要快速的安全的调整
你的程序用于团队协作开发
你的程序面向WPF和Silverlight,你想在两个平台间尽可能的复用代码。
由此可见,除非是做企业应用,一些小的程序并不适用Prism,它将会使你简单的问题更高复杂!
本节完,写的比较乱,也比较简单,下一步说一些概念。
UI Composition组合UI
如上图,该界面有六个View组合而成,各个View之间具有低藕合,轻依赖。他们之间可以通过Services,Command event进行交互。
布局
上图是布局的概念图,在Shell上定义了两个Region,Navigation和Main。订单列表的View被注入Navigation区域,订单View被注入Main区域。
命令系统
分为Command Delegation和Command Composition
这里的命令和WPF的不太一样,用起来也麻烦的多,通过DelegationCommand和CompositionCommand二个泛形类进行
如下代码
public OrderPresentationModel() { SaveOrderCommand = new DelegateCommand
通过构造函数指定Save方法为SaveOrderCommand的执行方法,当命令Execte时会调用该方法,CanSave方法为命令的CanExecte方法。外界能过SaveOrderCommand进行交互。
CompositionCommand通过RegisterCommand方法注册子命令,如果有一条子命令的CanExecte为false则整个组合命令不能执行。
事件系统
分成Event Service和Event Aaaregation
模块之间通过服务接口进行交互,模块之间不直接依赖,这和标准的.NET事件不同,Event Aaaregation类似,只是一个多个事件的组合服务。
模块化设计的好处
简化模块,定化高内聚低藕合的模块,模块间通过清晰的接口进行交互
模块可以独立开发布署
从不同的地方加载模块
最小化下载时间,下载时先下载启动必须的模块,其它模块在后台下载
最小化启动时间,可以运行时动态加载模块,减少程序的启动时间。
模块的概念图
内容都相对好理解,里面还针对Stock Trader 讲解了模块化设计的例子。
Container这部分参见Untity Application Block,
Multi-Targeting是讲在WPF和Silverlight之间最大化复用代码,由于WPF和Silverlight不兼容,并不共享assembly,只能共享代码,由于silverlight的API只是.net的子集,为了共享代码你可能需求变通的方法来实现某种功能,如果你只使用基本用户控件也可以在他们之间共享View。
总之复用代码并不是简单。
由于只是简单的概念介绍,打算到技术概念的时候再展现代码
Bootstrapper就是Prism的引导程序,我们知道在Composite UI Application Block时我们是通过继承FormShellApplication来引导我们的程序,它们的职责是一样的,它会为我们的程序做一些初始化的工作。如下图:
它按照上面的顺序帮我们做一些初始化工作,下面是Bootstrapper的类图
Bootstrapper里没有方法的执行步骤,所有的执行顺序由子类定义。
Bootstrapper里并不含Container,这是因为在4.0版本之前并由于只有一个UnitBootstrapper,并没有为它定义基类,它使用UnitContainer作为它的依赖注入容器,虽然宣称支持第三方的依赖注入如Spring.net,但Sprint.net不可能继承IUnityContainer,这意味着你不能使用UnitBootstrapper,你需要把UnitBootstrapper的功能全部重写,而且没有基本供你继承。我认为这是设计时的失误,在4.0时由于增加了MefBootstrapper,所以才有了这个基本。也有我们扩展自己的Bootstrapper提供了方便。
Bootstrapper在ConfigureRegionAdaperMappings中注册了一些默认的RegionAdaper,
regionAdapterMappings.RegisterMapping(typeof(Selector), ServiceLocator.Current.GetInstance
regionAdapterMappings.RegisterMapping(typeof(ItemsControl), ServiceLocator.Current.GetInstance
regionAdapterMappings.RegisterMapping(typeof(ContentControl), ServiceLocator.Current.GetInstance
如果我们自定义了自己的Region,需求在重写这个方法注册自己的RegionAdapter
我们看一下这二个引导程序的
UnitBootstrapper在Run方法中的执行顺序大致如下
CreateModuleCatalog();
ConfigureModuleCatalog()CreateContainer()
这些方法都是虚方法,我们根据需要重写这些方法,提供我们的Container、Module、Shell等。
MefBootstrapper的执行顺序和UnitBootstrapper的类似,只是多了二步CreateAggregateCatalog()和ConfigureAggregateCatalog()
下面看一下使用的例子,我们知道在WPF中通过App.XAML中的StartURL指定程序的MainWindows,这里我们需要用在我们需要在创建主窗体前做一些初始化工作,所以我们在删除StartURL,用Bootstrapper来创建主窗体。
我们继承UnitBootStrapper
Bootstrapper
代码很简单,在ConfigureModuleCatalog中增加HelloWorldModule,创建Shell,并且指定它为App的MainWindows.
我们在App的OnStartup方法中创建Bootstrapper并且调用他的Run方法即可.
Shell的定义如下
Shell
在Shell中指定了一个MaiRegion,
在HelloWordModule中我们指定按HelloWordView显示在MainRegion中
HelloWorldModule
这样一个HelloWorld的程序就完成了,由于只是说Bootstrapper,所有用了Prism中最简单的HelloWord示例,代码在Prism中有.
以后我们会试下自定义一个Bootstrapper,这里只是一个入门
Prism的依赖注入支持Unity,但不仅限于Unity,Prism通过IServiceLocator来构造对象,定义如下
IServiceLocator
还有一个IServiceLocator的扩展类
ServiceLocatorExtensions
默认为我们提供了,UnityServiceLocatorAdaper,看名字就知道它是一个适配器,用来连接Unity和IServiceLocator,
UnityServiceLocatorAdapter
UnityServiceLocatorAdapter的定义出人意料的简单,仅仅二个方法,它继承自Microsoft.Practices.ServiceLocation.dll里的ServiceLocatorImplBase,
这个类的定义也是非常简单,里面的代码仅仅是将对方法的调用委托给DoGetInstance和DoGetAllInstances这二个虚方法,代码很精简,在UnityBootstraper里通过UnityContainer来获取UnityServiceLocatorAdaper,再由UnityServiceLocatorAdaper取得各种服务。在UnityBootstrapper里通过调用
RegisterTypeIfMissing(typeof(IServiceLocator), typeof(UnityServiceLocatorAdapter), true);
接下来我们就可以能过serviceLocator来使用Unity提供的依赖注入功能。
如果我们要护展使用第三方的依赖注入容器,就可以通过继承ServiceLocatorImplBase,重写他拉两个虚方法,然后实现我们自定义的Bootstrapper,下面是MefServiceLocatorAdaper的实现代码
UnityServiceLocatorAdapter
是不是也很简单呀