首先在介绍本节内容之前,首先来看看官方文档来如何描述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中的容器......

												

Prism框架研究(二)的更多相关文章

  1. Prism框架研究(一)

    从今天起开始写一个Prism框架的学习博客,今天是第一篇,所以从最基本的一些概念开始学习这个基于MVVM的框架的学习,首先看一下Prism代表什么,这里引用一下比较官方的英文解释来看一下:Prism ...

  2. Prism框架研究(三)

    这一篇主要用来介绍一下基于Prism Library中的核心服务以及如何配置Container,还有一个重要的部分是如何管理各个组件之间的依赖性,下面就这些内容来做一一的介绍. 1 Prism中的核心 ...

  3. 【原创】NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示

    前言 NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能.这其中最流行的无非就是MINA和Netty了,MINA目前的主要版本是MINA2.而Netty的主要版本是Netty3和Netty ...

  4. 在Prism 框架中,实现主程序与模块间 UI 的通信

    背景: 在模块的UI中包含 TreeView 控件,在该树形控件的每一节点前面定义了一个复选框,如图 需求: 在两个不同的应用程序中使用该控件,而它在不同应用程序中的外观则并不一致,按照本例,即一个显 ...

  5. ASP.NET Web API 框架研究 ASP.NET Web API 路由

    ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...

  6. Prism框架的Module(模块化)编程

    Prism框架用的是新版本的,Prism7.1.关于其中的变动,感兴趣的参考https://www.cnblogs.com/hicolin/p/8694892.html 如何告诉Shell(我们的宿主 ...

  7. 【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入

    前言:在C/S架构上,WPF无疑已经是"桌面一霸"了.在.NET生态环境中,很多小伙伴还在使用Winform开发C/S架构的桌面应用.但是WPF也有很多年的历史了,并且基于MVVM ...

  8. MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)

    前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...

  9. JavaScript 框架设计(二)

    JavaScript 高级框架设计 (二) 上一篇,JavaScript高级框架设计(一)我们 实现了对tag标签的选择 下来我们实现对id的选择,即id选择器. 我们将上一篇的get命名为getTa ...

随机推荐

  1. [Python] Python 100例

    题目1:有四个数字:1.2.3.4,能组成多少个互不相同且无重复数字的三位数?各是多少? 程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. #程序源 ...

  2. 强化学习(三)—— 时序差分法(SARSA和Q-Learning)

    1.时序差分法基本概念 虽然蒙特卡洛方法可以在不知道状态转移概率矩阵的前提下,灵活地求解强化学习问题,但是蒙特卡洛方法需要所有的采样序列都是完整的状态序列.如果我们没有完整的状态序列就无法用蒙特卡洛方 ...

  3. Nginx系列一:正向代理和反向代理、Nginx工作原理、Nginx常用命令和升级、搭建Nginx负载均衡

    转自https://www.cnblogs.com/leeSmall/p/9351343.html 仅供个人学习 一.什么是正向代理.什么是反向代理 1. 正向代理,意思是一个位于客户端和原始服务器( ...

  4. [ASP.NET]ScriptManager控件使用 转载

    目录 概述 局部刷新 错误处理 类型系统扩展 注册定制脚本 注册 Web 服务 在客户端脚本中使用认证和个性化服务 ScriptManagerProxy 类 添加 ScriptManager 控件 客 ...

  5. SWAP_JOIN_INPUTS Oracle Hint(处理hash join强制大表(segment_size大)作为被驱动表)

    SWAP_JOIN_INPUTS Oracle Hint(处理hash join强制大表(segment_size大)作为被驱动表) swap_join_inputs是针对哈希连接的hint,它的含义 ...

  6. python之type函数

    python 的type 函数 的介绍的   下面就是此函数的参数   三个参数的意义 '''type(class_name, base_class_tuple, attribute_dict)cla ...

  7. Pyhon流程控制

    1.条件控制 Python 中用 elif 代替了 else if,所以if语句的关键字为:if – elif – else. 注意: 1.每个条件后面要使用冒号 :,表示接下来是满足条件后要执行的语 ...

  8. .Net高级进阶,教你如何构建企业模型数据拦截层,动态控制字段验证

    现在,你有一个MVC架构的web项目,你要完成一个注册功能. 前台传了3个值到你的控制器,分别是账号.密码.邮箱. 如图:现在你要在控制器里面判断,账号名称.密码.邮箱不能为空,并且名称和密码不超过1 ...

  9. vuex mapState、mapGetters、mapActions、mapMutations的使用

    例子: index.js import Vue from 'vue' import Vuex from 'vuex' import mutations from './mutations' impor ...

  10. quartz获取缓存中所有运行中的Job

    原文地址:https://blog.csdn.net/zzm8421/article/details/77769203 Quartz 2.1.5: public static void getAllJ ...