Prism 5程序初始化过程

Prism在运行程序前,需要的组件像其他大部分程序架构一样在初始化阶段完成。Prism将这个启动加载器命名为Bootstarpper。在Bootstarpper中,按顺序加载一系列组件,如,moduleCatalog,container,还有UI的 regionAdapter,shell和module等等。

Bootstrapper

在Prism中,自带有基于Unity和MEF两种DI容器的Bootstrapper,分别为UnityBootstrapper和MEFBootstrapper。此文所有介绍都基于UnityBootstrapper,当然我们也可以定义自己的启动器(开闭原则,在后面的文章中还有很多类似的设计原则和设计模式)。Bootstrapper大部分方法是虚拟方法,定义如下:

  1 #region 程序集 Microsoft.Practices.Prism.Composition.dll, v5.0.0.0
  2 // F:\RefrenceProject\compositewpf-ff6316df3dadd0d24083d51aa1dea922d07fb47e\V5\Quickstarts\Hello World\HelloWorld.Desktop\packages\Prism.Composition.5.0.0\lib\NET45\Microsoft.Practices.Prism.Composition.dll
  3 #endregion
  4 
  5 using Microsoft.Practices.Prism.Logging;
  6 using Microsoft.Practices.Prism.Modularity;
  7 using Microsoft.Practices.Prism.Regions;
  8 using System;
  9 using System.Windows;
 10 
 11 namespace Microsoft.Practices.Prism
 12 {
 13     // 摘要: 
 14     //     Base class that provides a basic bootstrapping sequence and hooks that specific
 15     //     implementations can override
 16     //
 17     // 备注: 
 18     //     This class must be overridden to provide application specific configuration.
 19     public abstract class Bootstrapper
 20     {
 21         protected Bootstrapper();
 22 
 23         // 摘要: 
 24         //     Gets the Microsoft.Practices.Prism.Logging.ILoggerFacade for the application.
 25         protected ILoggerFacade Logger { get; set; }
 26         //
 27         // 摘要: 
 28         //     Gets the default Microsoft.Practices.Prism.Modularity.IModuleCatalog for
 29         //     the application.
 30         protected IModuleCatalog ModuleCatalog { get; set; }
 31         //
 32         // 摘要: 
 33         //     Gets the shell user interface
 34         protected DependencyObject Shell { get; set; }
 35 
 36         // 摘要: 
 37         //     Configures the Microsoft.Practices.Prism.Regions.IRegionBehaviorFactory.
 38         //     This will be the list of default behaviors that will be added to a region.
 39         protected virtual IRegionBehaviorFactory ConfigureDefaultRegionBehaviors();
 40         //
 41         // 摘要: 
 42         //     Configures the Microsoft.Practices.Prism.Modularity.IModuleCatalog used by
 43         //     Prism.
 44         protected virtual void ConfigureModuleCatalog();
 45         //
 46         // 摘要: 
 47         //     Configures the default region adapter mappings to use in the application,
 48         //     in order to adapt UI controls defined in XAML to use a region and register
 49         //     it automatically.  May be overwritten in a derived class to add specific
 50         //     mappings required by the application.
 51         //
 52         // 返回结果: 
 53         //     The Microsoft.Practices.Prism.Regions.RegionAdapterMappings instance containing
 54         //     all the mappings.
 55         protected virtual RegionAdapterMappings ConfigureRegionAdapterMappings();
 56         //
 57         // 摘要: 
 58         //     Configures the LocatorProvider for the Microsoft.Practices.ServiceLocation.ServiceLocator.
 59         protected abstract void ConfigureServiceLocator();
 60         //
 61         // 摘要: 
 62         //     Create the Microsoft.Practices.Prism.Logging.ILoggerFacade used by the bootstrapper.
 63         //
 64         // 备注: 
 65         //     The base implementation returns a new TextLogger.
 66         protected virtual ILoggerFacade CreateLogger();
 67         //
 68         // 摘要: 
 69         //     Creates the Microsoft.Practices.Prism.Modularity.IModuleCatalog used by Prism.
 70         //
 71         // 备注: 
 72         //     The base implementation returns a new ModuleCatalog.
 73         protected virtual IModuleCatalog CreateModuleCatalog();
 74         //
 75         // 摘要: 
 76         //     Creates the shell or main window of the application.
 77         //
 78         // 返回结果: 
 79         //     The shell of the application.
 80         //
 81         // 备注: 
 82         //     If the returned instance is a System.Windows.DependencyObject, the Microsoft.Practices.Prism.Bootstrapper
 83         //     will attach the default Microsoft.Practices.Prism.Regions.IRegionManager
 84         //     of the application in its Microsoft.Practices.Prism.Regions.RegionManager.RegionManagerProperty
 85         //     attached property in order to be able to add regions by using the Microsoft.Practices.Prism.Regions.RegionManager.RegionNameProperty
 86         //     attached property from XAML.
 87         protected abstract DependencyObject CreateShell();
 88         //
 89         // 摘要: 
 90         //     Initializes the modules. May be overwritten in a derived class to use a custom
 91         //     Modules Catalog
 92         protected virtual void InitializeModules();
 93         //
 94         // 摘要: 
 95         //     Initializes the shell.
 96         protected virtual void InitializeShell();
 97         //
 98         // 摘要: 
 99         //     Registers the System.Types of the Exceptions that are not considered root
100         //     exceptions by the Microsoft.Practices.Prism.ExceptionExtensions.
101         protected virtual void RegisterFrameworkExceptionTypes();
102         //
103         // 摘要: 
104         //     Runs the bootstrapper process.
105         public void Run();
106         //
107         // 摘要: 
108         //     Run the bootstrapper process.
109         //
110         // 参数: 
111         //   runWithDefaultConfiguration:
112         //     If true, registers default Prism Library services in the container. This
113         //     is the default behavior.
114         public abstract void Run(bool runWithDefaultConfiguration);
115     }
116 }
View Code

Bootstrapper初始化的顺序如下:

Basic stages of the bootstrapping process

 

上图不难理解,软件记录日志,包括Bootstrapper的启动过程,所以Logger启动在第一位,生成和配置DI容器放在第三位,因为下面所有的操作依赖于使用容器解耦,,ModuleCatalog,并不依赖DI容器,可以放在第二位,下面的RegionAdapter和RegionBehavior也差不多意思,至于为什么Module放在最后,其实也无他,也是因为Module(模块)属于Shell(主窗体)。

因此,在使用Prism前,你必须先决定:

  1. 使用Unity或MEF,或其他DI容器。当然,如果使用其他注入容器,也决定了要自定义Bootstrapper。
  2. 你还可能需要把你程序的服务注册到container(DI容器),以方便各个Module(模块)的解释使用。
  3. 决定内置的日志组件是否适合,否则重写CreateLogger。
  4. 决定如何注册你的Module,使用配置文件还是XAML还是目录发现(需要在模块类使用特征标识 )还是直接写死在代码。

选择DI容器,很easy,熟悉哪种选哪种,使用也很简单,只需要继承一下就可以。

using System.Windows;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Prism.UnityExtensions;

namespace HelloWorld
{
    class Bootstrapper : UnityBootstrapper
    {
               
    }

 

Bootstrapper是Prism的入口,因此,要指定APP.xaml的Bootstrapper

 1 using System.Windows;
 2 
 3 namespace HelloWorld
 4 {
 5     /// <summary>
 6     /// Interaction logic for App.xaml
 7     /// </summary>
 8     public partial class App : Application
 9     {
10         protected override void OnStartup(StartupEventArgs e)
11         {
12             base.OnStartup(e);
13             Bootstrapper bootstrapper = new Bootstrapper();
14             bootstrapper.Run();
15         }
16     }
17 }
View Code

 

CreateShell

createShell是必须要继承的,因为必须指定主窗体。

    class Bootstrapper : UnityBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            return this.Container.Resolve<Shell>();
        }
    }

这里使用DI容器的Resolve方法,这种方法的好处是把Shell所有需要的引用的DLL都自动引入。当然也可直接new一个主窗体对象出来。

进一步,可以使用ServiceLocator,ServiceLocator也是IOC的一种实现,类似DI也是IOC的一种实现。ServiceLocator最终还是调用DI容器,至于是Unity还是MEF,这是ServiceLocator要关心的事了,我们在这不作更深入的了解。

protected override DependencyObject CreateShell()
{
    return ServiceLocator.Current.GetInstance<Shell>();
}

InitializeShell 

Shell初始化所需的工作应该写在这里。

protected override void InitializeShell()
{
    Application.Current.MainWindow = Shell;
    Application.Current.MainWindow.Show();
}

当然也可以把所有初始化工作写到CreateShell()里,IntializeShell不重写,但总感觉有点怪怪的。

CreateModuleCatalog

在调用CreateModuleCatalog之前,Prism会调用CreateModuleCatalog,生成ModuleCatalog。使用模块化开发,需要实现CreateModuleCatalog方法添加Module。

        protected override void ConfigureModuleCatalog()
        {
            base.ConfigureModuleCatalog();

            ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog;
            moduleCatalog.AddModule(typeof(HelloWorldModule.HelloWorldModule));
        }

ConfigureContainer

配置Container(DI容器),Container在Prism中具有非常重要的角色,在使用Prism开发的代码中,常常见到这个家伙。在Container的配置阶段,需要把核心服务注册到Container,当然也要把业务上的关键服务注册到Container。

基类代码实现如下:

 1         protected virtual void ConfigureContainer()
 2         {
 3             this.Logger.Log(Resources.AddingUnityBootstrapperExtensionToContainer, Category.Debug, Priority.Low);
 4             this.Container.AddNewExtension<UnityBootstrapperExtension>();
 5 
 6             Container.RegisterInstance<ILoggerFacade>(Logger);
 7 
 8             this.Container.RegisterInstance(this.ModuleCatalog);
 9 
10             if (useDefaultConfiguration)
11             {
12                 RegisterTypeIfMissing(typeof(IServiceLocator), typeof(UnityServiceLocatorAdapter), true);
13                 RegisterTypeIfMissing(typeof(IModuleInitializer), typeof(ModuleInitializer), true);
14                 RegisterTypeIfMissing(typeof(IModuleManager), typeof(ModuleManager), true);
15                 RegisterTypeIfMissing(typeof(RegionAdapterMappings), typeof(RegionAdapterMappings), true);
16                 RegisterTypeIfMissing(typeof(IRegionManager), typeof(RegionManager), true);
17                 RegisterTypeIfMissing(typeof(IEventAggregator), typeof(EventAggregator), true);
18                 RegisterTypeIfMissing(typeof(IRegionViewRegistry), typeof(RegionViewRegistry), true);
19                 RegisterTypeIfMissing(typeof(IRegionBehaviorFactory), typeof(RegionBehaviorFactory), true);
20                 RegisterTypeIfMissing(typeof(IRegionNavigationJournalEntry), typeof(RegionNavigationJournalEntry), false);
21                 RegisterTypeIfMissing(typeof(IRegionNavigationJournal), typeof(RegionNavigationJournal), false);
22                 RegisterTypeIfMissing(typeof(IRegionNavigationService), typeof(RegionNavigationService), false);
23                 RegisterTypeIfMissing(typeof(IRegionNavigationContentLoader), typeof(UnityRegionNavigationContentLoader), true);
24             }
25         }
View Code

如果我们只是实现业务,不需要对Prism二次开发的话,对业务服务的注册,只需要重写ConfigureContainer即可。

    class Bootstrapper : UnityBootstrapper
    {
        protected override void ConfigureContainer()
        {
            base.ConfigureContainer();

            this.RegisterTypeIfMissing(typeof(IModuleTracker), typeof(ModuleTracker), true);
            this.Container.RegisterInstance<CallbackLogger>(this.callbackLogger);
        }
    }

 

至此,Prism的初始化已介绍完毕。

 

posted @ 2016-01-26 17:27 Andy Ho 阅读(...) 评论(...) 编辑 收藏