Prism是由微軟Patterns & Practices團隊開發(fā)的項目,目的在于幫助開發(fā)人員構(gòu)建松散耦合的、更靈活、更易于維護并且更易于測試的WPF應(yīng)用或是Silverlight應(yīng)用以及Windows Phone 7應(yīng)用。使用Prism可以使程序開發(fā)更趨于模塊化,整個項目將由多個離散的、松耦合的模塊組成,而各個模塊又可以又不同的開發(fā)者或團隊進行開發(fā)、測試和部署。目前Prism的最新版本是Prism 4,于2010年11月12日發(fā)布。Prism有很完整的文檔以及豐富的示例程序。在這里我們僅針對于Silverlight程序的開發(fā)。
在下載Prism安裝包并安裝完成后,會在目標(biāo)文件夾中發(fā)現(xiàn)很多文件。
推薦首先運行RegisterPrismBinaries.bat文件,這樣在開發(fā)基于Prism的程序時可以更方便地添加引用程序集。
使用Prism之前,需要了解一些概念,下面通過一個非常簡單的小程序來了解一下Prism。
1.打開Visual Studio 2010,新建一個Silverlight Application項目,并添加對Prism的引用。再創(chuàng)建三個Silverlight類庫工程。
2.在Contract工程下新建一個接口,叫做ITextProvider。
public interface ITextProvider
{
string GetText();
}
3.在其它的三個項目中都引用Contract項目。
4.在PrismStarter工程下新建一個TextProvider類并實現(xiàn)ITextProvider接口。
public class TextProvider : ITextProvider
{
private int i = 0;
public string GetText()
{
i++;
return string.Format("From TextProvider [{0}]", i);
}
}
5.刪除PrismStarter項目中自動生成的MainPage.xaml,創(chuàng)建一個新的UserControl,叫做Shell。頁面代碼如下:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://www.codeplex.com/prism"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
6.在ModuleA工程中添加對Prism程序集的引用。并添加一個UserControl叫做ViewA,頁面代碼為:
CodeBehind中的代碼為:
public partial class ViewA : UserControl
{
public ViewA(ITextProvider textProvider)
{
InitializeComponent();
this.Loaded += (s, e) =>
{
textModuleA.Text = string.Format("Module A {0}", textProvider.GetText());
};
}
}
7.在ModuleA工程中添加一個類叫做ModuleA,并實現(xiàn)接口IModule。
public class ModuleA : IModule
{
private IRegionManager _regionManager;
public ModuleA(IRegionManager regionManager)
{
_regionManager = regionManager;
}
public void Initialize()
{
_regionManager.RegisterViewWithRegion("RegionA", typeof(ViewA));
}
}
注意這里的RegionA對應(yīng)于Shell頁面中的RegionName。
8.在ModuleB工程中重復(fù)6、7過程,只是將A替換為B。
9.在PrismStarter工程中添加對ModuleA和ModuleB的引用。
10.在PrismStarter工程中添加一個PrismStarterBootstrapper類,并繼承UnityBootstrapper。
public class PrismStarterBootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return this.Container.TryResolve();
}
protected override void InitializeShell()
{ // 控制頁面在初始化時顯示Shell頁面
App.Current.RootVisual = (UIElement)this.Shell;
}
protected override void ConfigureModuleCatalog()
{ // 注冊Module。在實際開發(fā)中可以使用xaml做配置文件,
// 這樣就可以將PrismStarter與ModuleA和ModuleB完全解耦,也就不再需要引用這兩個項目
Type moduleAType = typeof(ModuleA.ModuleA);
ModuleInfo moduleA = new ModuleInfo
{
ModuleName = moduleAType.Name,
ModuleType = moduleAType.AssemblyQualifiedName,
};
Type moduleBType = typeof(ModuleB.ModuleB);
ModuleInfo moduleB = new ModuleInfo
{
ModuleName = moduleBType.Name,
ModuleType = moduleBType.AssemblyQualifiedName,
};
this.ModuleCatalog.AddModule(moduleA);
this.ModuleCatalog.AddModule(moduleB);
}
protected override void ConfigureContainer()
{ // 注冊一下TextProvider,這樣在通過容器請求ITextProvider時會返回TextProvider實例
base.ConfigureContainer();
this.Container.RegisterInstance(new TextProvider());
}
}
11.最后一步,打開App.xaml.cs,修改Application_Startup方法
private void Application_Startup(object sender, StartupEventArgs e)
{
PrismStarterBootstrapper bootstrapper = new PrismStarterBootstrapper();
bootstrapper.Run();
}
運行程序,結(jié)果如下:
下面簡單介紹一下這個小例子中涉及到的一些概念。
Bootstrapper: 在程序中使用框架需要找到一個切入點,將框架植入進去,將一部分功能委托給框架來實現(xiàn)。在Silverlight中使用Prism的切入點就是App.xaml.cs中的Application_Startup方法。一般來說,這個方法中只是指定頁面最先加載的頁面,但是我們把默認(rèn)的邏輯去掉,取而代之的是Bootstrapper(在本例中就是PrismStarterBootstrapper)。當(dāng)調(diào)用Bootstrapper.Run方法時,它會完成一些準(zhǔn)備工作,如一些配置等。因此你會發(fā)現(xiàn),使用Prism后,啟動程序時會比正常啟動要慢一些,就是因為Bootstrapper做了許多工作。
Container: 依賴注入容器。在程序中使用依賴注入的好處到處都可以找的到。在Silverlight中使用容器來管理各個組件的一個很明顯的好處就是使用單例來降低內(nèi)存使用。否則每次加載一個頁面都需要重新創(chuàng)建一個也很耗費資源的。當(dāng)然好處不只這些,通過容器來注入一些服務(wù)(如本例中的IRegionManager和ITextProvider)顯得相當(dāng)方便。
Module: Prism幫助我們把程序分解成一個個功能模塊,這些功能模塊就叫做Module,通常一個工程就是一個Module。由于Module彼此是獨立的,但是在運行時需要將它們整合到一起,因此Prism需要知道Module的存在,這里就涉及到了ModuleCatalog, ModuleCatalog就是Module的容器,里面包含了所有Module的信息,以ModuleInfo的形式存在。ModuleInfo就是對Module的抽象,包含Module的名字,類型,依賴等一些信息。
Shell: 相當(dāng)于程序的入口,初始界面,還能夠提供類似ASP.Net中的母版頁的功能。Shell必須由Bootstrapper創(chuàng)建,因為Shell需要使用的一些service,比如RegionManager等,需要在Shell顯示前注冊。
Region: 相當(dāng)于ASP.Net中的ContentPlaceHolder(是這么叫的吧?),起到占位符的作用,如本例中Shell中有兩個Region——RegionA和RegionB,定義了兩塊區(qū)域。在Module的初始化過程中,通過IRegionManager將Module中的頁面放進了定義好的Region中。IRegionManager負(fù)責(zé)管理Region,可以通過它向Region中注冊View,進行導(dǎo)航等。
Prism的功能當(dāng)然遠不止這么簡單,它還提供對MVVM模式的支持,對導(dǎo)航的支持等,在后續(xù)文章中會逐步介紹。希望能夠通過本文讓大家對Prism有一定的了解。