在现代软件开发中,模块化和解耦是提高软件可维护性和可扩展性的关键。Prism框架正是为了帮助开发者设计出松耦合的组件,这些组件可以无缝集成和开发。每个应用程序都需要从某个地方开始,对于Prism应用程序来说,Bootstrapper和Shell是启动的关键。本文将深入探讨Bootstrapper及其初始化过程。
Bootstrapper是负责初始化应用程序的类。那么,它需要初始化什么呢?首先,需要初始化的是核心服务,然后是应用程序特定的服务。
核心服务是Prism库提供给非应用程序特定的服务,包括:
除了核心服务,Prism还初始化一些应用程序特定的服务。这些服务是特定于应用程序的,并且在所有应用程序模块中都是通用的。例如,如果正在开发一个RSS类型的应用程序,那么RSS Feed服务就是一个应用程序特定的服务,几乎所有的模块都会使用它来读取Feed。
Bootstrapper是一个非常重要的类,它控制着每个组件的装配过程。Prism库提供了一个默认的抽象Bootstrapper基类,其中包含许多虚拟方法。让来看一下Bootstrapper的过程。请记住,这个过程的大多数阶段将在后续文章中更详细地介绍。
首先,需要创建一个LoggerFacade,它主要负责日志记录。接下来,需要配置模块目录。然后,需要创建一个容器,可以选择任何容器,如Ninject、Unity、MEF等。Prism库实际上包括两个Bootstrapper类。一个叫做UnityBootstrapper,另一个是MEF,它包含了使用Unity或MEF作为依赖注入容器所需的大部分功能。
接下来,需要配置默认的区域适配器映射。因此,需要创建一个自定义的区域适配器,并在那里注册。然后,需要配置默认的区域行为。接着,将注册框架异常类型。然后,将创建Shell。接着,Shell将被初始化。最后,模块将被初始化。
请记住,不需要实现每一个阶段。
为了使用Unity,需要向项目添加以下引用:
Microsoft.Practices.Prism.dll
Microsoft.Practices.Prism.UnityExtensions.dll
Microsoft.Practices.Prism.Unity.dll
接下来,需要添加一个名为Bootstrapper的类,如下:
C#
public class Bootstrapper : UnityBootstrapper
{
protected override System.Windows.DependencyObject CreateShell()
{
return Container.Resolve();
}
protected override void InitializeShell()
{
base.InitializeShell();
App.Current.MainWindow = (Window)Shell;
App.Current.MainWindow.Show();
}
}
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Bootstrapper bootstrapper = new Bootstrapper();
bootstrapper.Run();
}
}
在本节中,将讨论Prism应用程序中区域的作用。将讨论区域是什么以及它们在应用程序中的作用。还将查看RegionManager以及它如何管理Prism应用程序。还将探讨区域适配器以及区域和RegionManager之间的关系。然后,将看到如何创建自定义区域,这对于Prism不支持的控件是必要的。
区域简单地说就是UI中将要呈现的任何动态内容的占位符。区域类似于ASP.NET的内容占位符。它只是一个命名位置,可以用来定义视图将出现的地方。希望记得之前讨论过Shell的概念以及如何包含区域,将视图注入到这些区域。
现在让快速举一个例子。在这个例子中,将有一个MenuBar区域和一个Content区域。这些区域定义了UI的区域,视图将被注入。每个区域应该明确命名,并描述将注入区域的内容类型。假设有一个模块,包含两个视图,分别命名为MenuBar视图和ContentView。这些视图将被注入到它们各自的区域。这意味着每个区域将有其对应的视图。这里MenuBar视图将被注入到MenuBar区域,ContentView将被注入到Content区域。
现在,请记住,不仅仅在Shell中定义区域,区域也可以在另一个视图中定义。区域对视图一无所知。可以将内容定位到区域,而不需要确切地知道区域是如何定义的。这允许在不影响模块中的视图的情况下更改布局。例如,在上图中,可以将'MenuBar区域'移动到'Content区域'的左侧,但'MenuBar视图'将被注入到'MenuBar区域','ContentView'仍然会被放置到'Content区域'。因此,可以重新设计Shell,而不需要重新编写任何类型的基础设施代码。
区域可以在代码中或在XAML中创建。需要记住的一件事是,区域不是一个控件,而是一个宿主控件,它总是实现IRegion接口。这很重要,因为当在程序中访问区域时会使用它。
希望中的许多人可能已经猜到了,区域管理器负责管理应用程序中的区域。它通过维护区域的集合来实现这一点。它还提供了一个RegionName属性。这实际上是一个附加属性,用于通过将其应用到宿主控件上来创建区域,这可以通过XAML或代码再次完成。
区域管理器还将区域适配器映射到控件。现在,区域适配器负责将区域与宿主控件关联起来。为了将UI控件暴露为区域,它必须有一个区域适配器,每个区域适配器适应特定类型的UI控件。
Prism为提供了四种区域适配器:
现在,如果Prism提供的区域适配器不满足需求,完全可以创建自己的。
区域管理器还提供了一个RegionContext附加属性。这个属性类似于DataContext的概念。它是一种在父视图和子视图之间共享数据的技术。RegionContext也可以从代码或XAML中设置。
为了创建一个区域,需要在XAML(Shell)中添加以下引用:
xmlns:local="http://www.codeplex.com/prism"
接下来,需要创建区域,如下:
<DockPanel>
<ContentControl DockPanel.Dock="Top" local:RegionManager.RegionName="MenuBarRegion" />
<ContentControl local:RegionManager.RegionName="ContentRegion" />
</DockPanel>
然后,转到Module类并添加以下内容:
C#
public class MyModule : IModule
{
IUnityContainer _container;
IRegionManager _regionManager;
public MyModule(IUnityContainer container, IRegionManager regionManager)
{
_container = container;
_regionManager = regionManager;
}
public void Initialize()
{
regionManager.RegisterViewWithRegion(
"MenuBarRegion",
typeof(MenuBarView));
regionManager.RegisterViewWithRegion(
"ContentRegion",
typeof(ContentView));
}
}