Prism - 第一個!超簡單Prism範例
這篇的內容,主要是翻譯於這個網站的內容,是由國外的Nick Polyak高手所寫的,然後再加上小弟雜多的解釋內容XDD,所以內容不是百分百和原網站一樣,而且差異甚大,如有不好之處,也請各位多多包涵 ( 所以這篇可以算是讀後心得了,不算翻譯文了.. )
最簡單的Prism程式
這裡示範的第一個最簡單的Prism程式,為什麼叫做最簡單呢!?因為這個範例裡面完全沒有任何的視覺效果,也就是說,不會放一些啥Button等等之類的Control,只有最簡單的東西,運作出來的結果如下,我們可以看到畫面非常的單純, 單純到沒有任何東西XDD。
雖然一片空白,但裡面有很多學問=w=,接下來,我們看看怎樣來做這個範例。
實作Main Project
首先我們先建立一個Silverlight應用程式,並且把不需要的東西先刪除掉,這裡我們把MainPage.xaml刪除掉,所以目前專案架構會變成如下圖;因為這個範例我們沒有打算使用到視覺的部分,只是單純的希望能了解他的架構,所以我們用不到MainPage.xaml,就先刪除掉吧。
這邊我們需要參考兩個dll,這兩個dll分別在安裝Prism的bin目錄下面,分別是Microsoft.Practices.Prism.dll和Microsoft.Practies.Prism.MefExtension.dll。
接下來,我們要改變一下App.xaml.cs的程式碼,位置如下圖。
我們打開App.xaml.cs的程式碼,會發現裡面有錯誤;這是很正常的,因為我們已經把MainPage.xaml砍掉了,所以我們要改變一下這邊的程式碼。
修改App.xaml.cs的Application_Startup
改成如下;打的時候會發現TheBootstrapper找不到,不過那是正常的,因為這個Class我們還沒撰寫,我們這邊改用TheBootstrapper來取代原本程式執行時預設顯示的View,如果是原本程式架構,當程式執行時,會將MainPage.xaml給實例化起來,並且變成預設的根畫面( RootVisual,也就是最底層的畫面 ),但我們使用Prism時,不會使用原本的MainPage.xaml ( 無論是不是這簡單的範例都一樣,都會改變這行);因為使用Prism的時候,需要的東西和原本預設的MainPage.xaml是完全不一樣的,所以改用Prism時,我們會使用自己建立的Bootstrapper Class來產生整個Prism所需要的東西,而這裡我們自己建立的Bootstrapper Class稱為TheBootstrapper。
private void Application_Startup(object sender, StartupEventArgs e) { (new TheBootstrapper()).Run(); }
撰寫Bootstrapper Class
接下來,我要要建立一個TheBootstrapper.cs類別,內容如下;這個Class將替我們產生Prism所需要的Shell( 也就最上層的View )和整個底層的組件,Bootstrapper也會註冊一些需要用到的服務( 這裡使用MEF,所以必須繼承於MefBootstrapper )。
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Practices.Prism.MefExtensions; using Microsoft.Practices.Prism.Modularity; namespace PrismDeom1NoVirual { public class TheBootstrapper : MefBootstrapper { protected override void InitializeShell() { base.InitializeShell(); // 這裡是給Silverlight用,如果是WPF會不一樣。 Application.Current.RootVisual = (UIElement)Shell; } // 建立Shell的方法,shell在Prism Application是主要的View // 在這個範例,我們只想了解BootStrapper,所以我們把原本的MainPage刪掉。 // 並且利用Grid當作主要的Shell protected override DependencyObject CreateShell() { return new Grid(); } protected override IModuleCatalog CreateModuleCatalog() { ModuleCatalog moduleCatalog = new ModuleCatalog(); //在這邊,我們使用moduleCatalog來加載模組進來。 moduleCatalog.AddModule ( new ModuleInfo { InitializationMode = InitializationMode.WhenAvailable, Ref = "Module1.xap", ModuleName = "Module1Impl", ModuleType = "Module1.Module1Impl, Module1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" } ); return moduleCatalog; } } }
在這邊,需要注意到這個Class執行Function的一個順序性( 未來會有一篇來探討原始碼 ),我們接下來看看這順序性是如何,我們這個Bootstrapper只有Override三個Function,你會發現他最先執行的Function是CreateModuleCatalog(),也就是說,他會先建立moduleCatalog這個Class,這個Class的用途是紀錄目前有哪些module,並準備利用MEF的方式去做個組合,寫法就如上面的程式碼一樣( 等下會去建立Module );第二個執行的Function是CreateShell(),我們把原本在ApplicationStartup方法裡面建立View的任務,移到這裡來,而這邊,我們直接new一個Grid,畢竟原本的MainPage.xaml被我們刪除掉了;第三個要執行的Function是InitializeShell(),除了原本MEFBootstrapper原本就該執行的程式外,我們也把ApplicationStratup指定RootVisual的任務,寫在這邊;或許有人會問說,為什麼我會知道順序!?其實很簡單,因為我翻過原始碼…
建立Module Project
緊接著,我們要來建立Module,在Prism裡面,通常會把Module建立成獨立的專案來進行,所以我們建立一個新的專案,這邊要特別注意,要選擇的是Silverlight應用程式( Silverlight Application )而非Silverlight類別庫 ( Silverlight Class ),這是因為Module是一個xap,而非dll。
接下來,我們不需要額外的測試頁,所以把測試頁的勾選拿掉。
建立完新的專案後,把APP.xaml和MainPage.xaml刪除到( 這是因為我們這個範例沒用到 ),刪除完後,並建立一個Class,名稱取為Module1Impl.cs,完成後如下。
接下來,又要參照一些dll了,除了上面的那兩個dll要參照進來,還需要參照.NET Framework內建的System.ComponentModel.Composition。這裡因為我是使用Silverlight 5,所以使用5.0版本。
參照完後,在Module Project的地方,需要特別注意,我們要把參照到的Microsoft.Practices.Prism和Microsoft.Practies.Prism.MefExtension,複製到本機的選項改為False,這點要特別注意,如果設定為True,程式還是可以跑,也不會報錯,但就是不會加載Module進來 ( 只需要改Module的專案。 )。
撰寫Module1 Class
接下來,我們要撰寫Module,Module必須實作於IModule,而這邊會使用ModuleExport屬性來標記,讓Prism知道這是一個Module。
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Practices.Prism.Modularity; using Microsoft.Practices.Prism.MefExtensions.Modularity; namespace Module1 { //利用ModuleExport屬性來標記,這是一個Module [ModuleExport(typeof(Module1Impl))] public class Module1Impl : IModule { #region IModule Members public void Initialize() { } #endregion } }
最後,我們可以設定中斷點在這邊,當程式執行的時候,如果有進到這個中斷點,就表示有順利的去加載這個Module了。
後記
做到這邊,最簡單的Prism程式就完成了,在Prism裡面,如果用的是MEF框架,那建議先稍微懂一下MEF會比較好,不然做下來可能會湖煞煞,如果有時間,也建議把IoC的部分有個理解,因為有很多地方,都是利用注入的概念;其實Prism就如許多前輩講的一樣,學習門檻真比較高,光是這邊文章,打打停停,也打了三天,而且其實還有很多東西還沒講得很仔細,這部分未來會再慢慢補充回來,如果覺得很有趣,迫不急待的人,也可以先看參考資料,繼續下去=w=。
參考資料