PRISM特點
PRISM是用來幫助設計和開發一個豐富,靈活,易於維護的WPF和Silverlight應用程式。PRISM庫檔案實現了一系列重要的設計模式和構架原則,比如關注點分離和松耦合。使用這些PRISM提供的設計模式和能力,可以中設計和實現多個使用各個關聯度很低但是卻可以輕鬆整合到一起的組件,並且使用它們組合成為一個系統。
在軟體開發過程中,一般認為分模組化地設計軟體總是比單一設計要好。然而模組化的設計也是有好壞之別的。它的最主要的兩個判斷方面就是松耦合和高內聚。耦合和內聚其實是獨立的,但是它們經常被用來一起判斷模組之間的依賴關係強不強。耦合是越松越好,兩個模組耦合越是緊,說明它們的依賴性越是強。只要一個模組改動,另一個模組也會不可避免的要去改動。如果是松耦合的話,就不會因為其他的模組改動而改動了。從內聚來說,是越高越好。如果一個模組有許多不相關的功能,那么它就不是高內聚的,是不好的。例如一個模組可能需要記下日誌來幫助日後的分析,但是日誌記錄並不是這個模組的內容,應該單獨把它寫入一個logging模組才是正確的選擇。
PRISM的關鍵概念
(1)Modules(模組):Modules是一些可以獨立開發,測試和(任意)部署的功.能包。通常不同的模組是由不同的團隊開發並且維護的。一個典型的PRISM包含了若干個模組。Modules可以用來表示有特定的業務關係的功能(如配置管理器profile management),並且封裝了視圖,服務,和實現所必要的數據模型。Modules也可以封裝一些系統通用模組或服務(如日誌,異常管理器)以方便它們在不同系統間復用 。
(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中的屬性。