• Prism框架研究(二)


      首先在介绍本节内容之前,首先来看看官方文档来如何描述Prism 应用的初始化吧!A Prism application requires registration and configuration during the application startup process—this is known as bootstrapping the application,也就是说在在一个Prism应用程序开始之前首先要做的就是注册和配注应用程序,我们以此为突破点,一步步来剖析。

         1 What is a Bootstrapper?

         Bootstrapper 是一个通过Prism Library来初始化一个应用程序的,我们来看看一个Bootstrapping process的基本步骤:

         

      2  什么是依赖注入?

      使用 Prism Library创建的应用程序依赖于容器提供的依赖注入, Prism Library提供了两种依赖注入容器:即Unity和MEF(Managed Extensibility Framework),在Prism应用程序中,Bootstrapper的一个重要的职责是创建shell(MainWindow),这是因为Shell依赖于各种服务,比如Region Manager服务,而这些服务恰恰是在Shell在创建之前需要被创建的。

         如果你确认是创建MEF或者是Unity容器作为依赖注入容器,那么正确的方法是创建一个类继承自这些容器,然后重写这些基类的虚方法和抽象方法,其中最重要的几个方法是:CreateShell()、InitializeShell()、CreateModuleCatalog(),现在来分别来介绍下这些方法。

      CreateShell():Creates the shell or main window of the application.具体的写法如下面的代码所示:

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

         仔细看,里面写了两个方法,都是可以的,这里的Shell是一个Window,是主程序,Container是定义在基类UnityBootstrapper中的一个方法,我们通过代码发现通过ServiceLocator.Current.GetInstance<Shell>(); 也能够达到同样的效果,那我们来看一看ServiceLocator到底是什么,实际上ServiceLocator在执行的时候也是通过调用 Container的。

      InitializeShell():在你创建了一个Shell之后,你需要通过InitializeShell()方法来确保Shell的呈现。下面以WPF程序为例来解释下面的代码。

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

      CreateModuleCatalog():该方法用来创建一个IModuleCatalog,IModuleCatalog的实例用来记录当前哪些模块对于应用程序是可用的,哪些模块是需要下载的,以及当前模块的归属。

          下面以一个具体的类来描述如何创建IModuleCatalog的实例。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Practices.Prism.Modularity;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.Diagnostics;
    using System.IO;
    
    namespace X.Core.Infrastructure
    {
        public class AggregateModuleCatalog : IModuleCatalog
        {
            private List<IModuleCatalog> catalogs = new List<IModuleCatalog>();
    
            public AggregateModuleCatalog()
            {
                this.catalogs.Add(new ModuleCatalog());
            }
    
            public ReadOnlyCollection<IModuleCatalog> Catalogs
            {
                get
                {
                    return this.catalogs.AsReadOnly();
                }
            }
    
            public void AddCatalog(IModuleCatalog catalog)
            {
                if (catalog == null)
                {
                    throw new ArgumentNullException("catalog");
                }
                this.catalogs.Add(catalog);
            }
    
    
            public IEnumerable<ModuleInfo> Modules
            {
                get
                {
                    return this.Catalogs.SelectMany(x => x.Modules);
                }
            }
    
            public IEnumerable<ModuleInfo> GetDependentModules(ModuleInfo moduleInfo)
            {
                var catalog = this.catalogs.Single(x => x.Modules.Contains(moduleInfo));
                return catalog.GetDependentModules(moduleInfo);
            }
    
            public IEnumerable<ModuleInfo> CompleteListWithDependencies(IEnumerable<ModuleInfo> modules)
            {
                var modulesGroupedByCatalog = modules.GroupBy<ModuleInfo, IModuleCatalog>(module => this.catalogs.Single(catalog => catalog.Modules.Contains(module)));
                return modulesGroupedByCatalog.SelectMany(x => x.Key.CompleteListWithDependencies(x));
            }
    
            public void Initialize()
            {
                foreach (var catalog in this.Catalogs)
                {
                    catalog.Initialize();
                }
            }
    
            public void AddModule(ModuleInfo moduleInfo)
            {
                this.catalogs[0].AddModule(moduleInfo);
            }
    
        }
    }
    

      最后一个需要进行重载的就是ConfigureModuleCatalog()这个方法,这个方法主要是用来配置IModuleCatalog的。

         这里也贴出一段代码来看看怎么重载上述的方法。  

    protected override void ConfigureModuleCatalog()
            {
                var catalog = ((X.Core.Infrastructure.AggregateModuleCatalog)ModuleCatalog);
    
                if (!System.IO.Directory.Exists(@".Apps"))
                {
                    System.IO.Directory.CreateDirectory(@".Apps");
                }
                if (!System.IO.Directory.Exists(@".Modules"))
                {
                    System.IO.Directory.CreateDirectory(@".Modules");
                }
    
                foreach (string dic in System.IO.Directory.GetDirectories(@".Apps"))
                {
                    DirectoryModuleCatalog catApp = new DirectoryModuleCatalog() { ModulePath = dic };
                    catalog.AddCatalog(catApp);
                }
                foreach (string dic in System.IO.Directory.GetDirectories(@".Modules"))
                {
                    DirectoryModuleCatalog catApp = new DirectoryModuleCatalog() { ModulePath = dic };
                    catalog.AddCatalog(catApp);
                }
    
                ConfigurationModuleCatalog configCatalog = new ConfigurationModuleCatalog();
                catalog.AddCatalog(configCatalog);
            }
    

      需要特别注意的是这里我们使用的是DirectoryModuleCatalog,来加载某一个路径下面的DLL,这些都是需要特别说明的,我们首先来看看对于DirectoryModuleCatalog的官方解释:Represets a catalog created from a directory on disk.代表的是一个从磁盘上创建的一个目录,DirectoryModuleCatalog将会扫描当前目录下的内容,定位那些继承自IModule的类,并且将他们添加到目录中去,通过反射的方式,当前程序集会加载到一个新的应用程序域中,当当前程序集被销毁的时候,当前应用程序域将会被摧毁。

         下面再介绍另外一段简单的加载应用程序域的方法,此方法不再是加载某一个路径下的应用程序。     

    protected override void ConfigureModuleCatalog()
            {
                base.ConfigureModuleCatalog();
                ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog;
                moduleCatalog.AddModule(typeof(HelloWorldModule.MyHelloWorldModule));        
    
            }
    

      这里直接加载MyHelloWorldModule,这个程序模块继承自IModule,下面贴出当前类的代码。

    using Microsoft.Practices.Prism.Modularity;
    using Microsoft.Practices.Prism.Regions;
    
    namespace HelloWorldModule
    {
        public class MyHelloWorldModule : IModule
        {
            private readonly IRegionViewRegistry regionViewRegistry;
    
            public MyHelloWorldModule(IRegionViewRegistry registry)
            {
                this.regionViewRegistry = registry;   
            }
    
            public void Initialize()
            {
                regionViewRegistry.RegisterViewWithRegion("MainRegion", typeof(Views.HelloWorldView));
            }
        }
    }
    

      这里有一个特别重要的内容,就是通过RegisterViewWithRegion这个函数将当前模块注入到MainRegion中去,那么这个MainRegion到底是哪个区域呢?

         我们再来看看Shell的前台中有些什么?     

    <Window x:Class="HelloWorld.Shell"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cal="http://www.codeplex.com/prism"
        Title="Hello World" Height="300" Width="300">
        <ItemsControl Name="MainRegion" cal:RegionManager.RegionName="MainRegion" />
    </Window>
    

      看到了吗?当Prism加载MyHelloWorldModule这个模块的时候,会匹配RegionManager.RegionName中的 MainRegion,并且将当前模块加载到ItemsControl 中去,关于这一点,在后续的系类中,我都会重点去介绍,下一节我将会重点介绍Prism中的一些重点服务以及创建和配置UnityBootstrapper中的容器......

    
    
  • 相关阅读:
    OpenStack 多节点纳管 vCenter 5.5
    OpenStack 多节点纳管 vCenter 5.5
    java.utils.UUID类介绍
    BeanUtils工具类
    Request笔记
    JavaEE_XMind总结
    JavaSE_XMind总结
    完成页面的定时跳转
    使用jsp完成商品列表的动态显示
    Respone笔记
  • 原文地址:https://www.cnblogs.com/seekdream/p/5843514.html
Copyright © 2020-2023  润新知