这一篇梳理Prism中07示例Module的几种加载方式。

07示例分为了5个,有5种不同的Module加载方式。

我们开始学习加载Modules

观察07-Modules-Appconfig示例

分为ModuleA工程和Modules工程

我们在解决方案上打开管理解决方案的Nuget程序包,ModuleA工程引用了Prism.Wpf;Modules引用了Prism.Unity;

Modules的App.config下配置文件被修改了。我们先不分析,就看一下结构。

<configuration>
<configSections>
<section name="modules" type="Prism.Modularity.ModulesConfigurationSection, Prism.Wpf" />
</configSections>
<startup>
</startup>
<modules>
<module assemblyFile="ModuleA.dll" moduleType="ModuleA.ModuleAModule, ModuleA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="ModuleAModule" startupLoaded="True" />
</modules>
</configuration>

1、ModuleA工程

ModuleA工程引用了Prism.Wpf。

1.1、新建ModuleAModule.cs

ModuleAModule类继承自IModule,该接口包含2个 方法OnInitialized和RegisterTypes;ModuleAModule中实现OnInitialized方法时使用了IContainerProvider调用了Resolve();

还有印象在第一篇中我们整理的,IRegionManager是一个区域管理,用于绑定区域和视图的,而这里就在做把ViewA使用regionManager的RegisterViewWithRegion()方法,向ContentRegion字符串对应的区域注册ViewA视图。通过上一篇的学习,我们知道这样就能直接把ViewA放在ContentRegion的区域,我们先不管逻辑实现。因为我们看到了配置文件中有这一块的内容,先不看。

  var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));

1.2、新建Views下的ViewA自定义控件,在Views的ViewA中只有一个显示控件显示了View A 字号为38。

2、Modules工程

Modules工程引用了Prism.Unity。

2.1App.xaml

添加命名空间xmlns:prism="http://prismlibrary.com/"

修改Application为prism:PrismApplication

取消StartupUri属性

2.2App.cs

继承类由Application修改为PrismApplication

重写CreateShell()方法,通过Container.Resolve解析MainWindow并返回,作为启动窗体;

重写RegisterTypes方法

重写CreateModuleCatalog(),返回一个ConfigurationModuleCatalog()对象。

 protected override IModuleCatalog CreateModuleCatalog()
{
return new ConfigurationModuleCatalog();
}

2.3Views下的MainWindow.xaml

有一个ContentControl显示控件,设置了附加依赖项属性,区域名称为ContentRegion。MainWindow.cs无特殊修改。

2.4运行代码,界面显示View A

总结:在Modules中做修改了App.config,设置了ConfigSections,我按照命名空间找过去,是使用ConfigurationStore配置Modules的。同时在App.config中也有配置的modules。里面写了assemblyFile、moduleType、moduleName、startupLoaded。也就是说这种方式是使用config配置文件的方式加载Modules,然后再对应的ModuleA或者其他名称的DLL中就可以通过containerProvider,和RegionManager来设置区域和视图的关联,但是客户端软件不推荐这种方法,因为客户端安装再客户电脑上,他可以通过自己修改app.config可以加载不同的模块。这样彻底解耦了DLL和主工程的引用关系。

观察07-Modules-Code示例

同样分为ModuleA和Modules两个工程,Modules工程引用了Prism.Unity;ModuleA工程引用了Prism.Wpf;

1、ModuleA工程

ModuleA工程引用了Prism.Wpf

1.1、新建ModuleAModule.cs

ModuleAModule类继承自IModule接口。并实现了该接口的2个方法,OnInitialized()、RegisterTypes,并再OnInitialized()方法中使用容器代理解析了IRegionManager,然后关联区域和显示界面。用于呈现。

1.2、Views下的ViewA.xaml

只包含了显示控件,显示View A,字号为38;

2、Modules工程

Moudules工程引用了Prism.Unity、ModuleA两个工程;

2.1、App.xaml

添加命名空间:xmlns:prism="http://prismlibrary.com/"

修改了Application为PrismApplication

去掉了StartupUri属性

2.2App.cs

App修改继承自PrismApplication

重写CreateShell()方法使用Container.Resolve解析MainWindow作为启动窗体;

重写RegisterTypes(不重写编译就报错)

重写ConfigureModuleCatalog方法

  protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<ModuleA.ModuleAModule>();
}

使用传入的moduleCatalog对象的AddModule方法,传入了ModuleA工程的ModuleAModule类型。

对比了上一篇appconfig篇,我们发现再App.cs中的ConfigureModuleCatalog方法是加载Module的。不同的加载类型,这里都需要重写这个方法。而使用Code加载Module的方法还需要引用工程。

2.3Views下的MainWindow.xaml

设置了ContentControl显示控件,并设置了附加依赖项属性用于设置区域名称为ContentRegion,后台cs中无额外代码

2.4运行Modules工程

界面显示View A。

总结:创建了ModuleA工程、Modules主工程,ModuleA引用了Prism.Wpf;主工程引用了Prism.unity;ModuleA两个工程,主工程通过引用项目的方式引入MouduleA,然后再通过重写PrismApplication的ConfigureModuleCatalog()加载了ModuleA下的ModuleAModule类。ModuleAModule类实现了IModule的OnInitialized()方法,并再该方法关联区域和显示视图,用于显示内容。这种加载方式感觉会比第一种好一些,我们继续往下看下一个例子。

观察07-Modules-Directory示例

分为ModuleA和Modules两个工程,ModuleA工程引用了Prism.Wpf、Modules工程引用了Prism.Unity;

1、ModuleA工程

ModuleA工程引用了Prism.Wpf;

1.1、新建了ModuleAModule.cs类

ModuleAModule继承自Prism.Modularity.IModule,并实现了OnInitialized()、RegisterTypes()

OnInitialized()方法同样使用传入的IContainerProvider容器代理对象Resolve解析出IRegionManager,然后使用这个RegionManager对象去关联一个区域和视图。

1.2、Views下的ViewA.xaml

和其他工程一样,包含一个显示控件显示一个ViewA 字号为38;cs文件中无新增代码。

2、Modules工程

Modules工程引用了Prism.Unity;

2.1、App.xaml

新增命名控件xmlns:prism="http://prismlibrary.com/"

修改Application为PrismApplication;

去掉StartupUri属性

2.2、App.cs

修改App继承自PrismApplication;

重写CreateShell()使用Container.Resolve()解析MainWindow用作启动窗体;

重写RegisterTypes() 不重写编译失败。

重写CreateModuleCatalog()方法

  protected override IModuleCatalog CreateModuleCatalog()
{
return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };
}

实例化了DirectoryModuleCatalog并传入了路径.\Modules,因为是从目录加载的,这里不知道是不是固定写法,然后所有自己创建的Module只要继承自IModule就行吗?这里没有验证,只是学习知道了可以从目录加载。继续往下。

3.1、Views下的MainWindow.xaml

包含了一个显示控件同时设置了附加依赖项属性区域名称ContentRegion。cs文件无新增代码。

4、先编译ModuleA、然后再运行Modules程序,不然报错;

界面显示View A

总结:使用Directory加载Module的话,再主工程中不需要引用各个Module,只需要配置目录的路径即可,但是没有验证新增ModuleB、C等等,是否可以自动加载进来,这个可以结合第一篇的代码,使用Resolve资源配合创建按钮,再各个Module中Activate和Deactivate修改主工程中区域名称对应的显示内容。

观察07-Modules - LoadManual示例

包含ModuleA和Modules两个工程;ModuleA引用了Prism.Wpf包;Modules引用了Prism.Unity包;

1、ModuleA工程

ModuleA工程只引用了Prism.Wpf;

1.1、新增ModuleAModule.cs

ModuleAModule继承自Prism.Modularity.IModule,并实现了OnInitialized()和RegisterTypes()接口,OnInitialized()方法和前面的项目一样,同样使用IContainerProvider容器代理Resolve解析RegionManager()对象,然后使用regionManager关联区域名称和对应的视图,用于显示。

1.2、Views下的ViewA.xaml

包含用于显示的TextBlock控件。显示内容为View A ,字号为38,cs文件中无修改;

2、Modules工程

Modules工程引用了Prism.Unity;和ModuleA项目;

2.1、App.xaml

增加命名空间prism="http://prismlibrary.com/"

修改Application为PrismApplication

去掉StartupUri属性

2.2App.cs

修改App继承自PrismApplication;

重写CreateShell()方法;

使用Container.Resolve()方法设置启动窗口为MainWindow。

重写RegisterTypes()方法,不重写编译报错。

重写ConfigureModuleCatalog()方法

        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
var moduleAType = typeof(ModuleAModule);
moduleCatalog.AddModule(new ModuleInfo()
{
ModuleName = moduleAType.Name,
ModuleType = moduleAType.AssemblyQualifiedName,
InitializationMode = InitializationMode.OnDemand
});
}

再添加ModuleA的工程引用后,直接使用typeof读取ModuleAModule。然后再moduleCatalog中使用AddModule方法,新建一个ModuleInfo()对象,包含了,Module的名称、限定名称、加载方式为按需加载;

2.3、Views下的MainWindow.xaml

设置了一个ContentControl 显示控件,并设置了附加依赖项属性用于关联显示区域ContentRegion。

添加了一个Button,注册了Click事件;

2.4、Views下的MainWindow.cs

我们来到CS文件中,我们看到了构造函数中初始化 IModuleManager对象,然后再用户点击Button的时候,使用LoadModule()方法加载ModuleAModule。

3、先编译ModuleA,再运行Modules

我们看到启动后,显示Load Module的Button,点击这个Button后显示View A文字。

总结:再Modules工程中,引入了Prism.Unity和ModuleA,再ModuleA中引用Prism.Wpf。

想使用LoadManual加载的方式,在App.cs中重写ConfiureModuleCatalog()方法时,获取typeof对应的ModuleA工程下的类对象,然后配置对应的程序集信息,在需要的地方,使用_moduleManager下的LoadModule()方法去加载对应的Module,各个Module去实现自己的IModule,用于在OnInitialized()中关联区域和视图。

观察07-Modules - Xaml示例

包含ModuleA工程和Modules工程两个工程,ModuleA引用了Prism.Wpf包、Modules引用了Prism.Unity包和ModuleA项目;

1、ModuleA工程

添加了对Prism.Wpf包的引用;

1.1、创建了ModuleAModule.cs类,继承了Prism.Modularity.IModule接口,实现了OnInitialized()和RegisterTypes()方法,并在OnInitialized()方法中使用传入的IContainerProvider对象调用Resolve发方法解析IRegionManager对象。然后使用IRegionManager的实例来关联字符串为ContentRegion和ViewA视图,用于显示。

1.2、Views下创建了用户自定义控件ViewA.xaml

里面有一个用户显示内容的TextBlock控件,显示内容为View A字号为38,cs文件中无新增内容

2、Modules工程

Modules引用了Prism.Unity包和ModuleA工程;

2.1、App.config

在App.config中添加了configSections节点,里面配置了Prism.Modularity.ModulesConfigurationSection和Modules节点,

用于添加引用Prism下的库,和加载ModuleA.dll的配置项;

2.2、App.xaml

添加了命名空间xmlns:Prism:="http://prismlibrary.com"

修改Application为PrismApplication

去掉StartupUri属性

2.3App.cs

修改App继承自PrismApplication

重写CreateShell()方法,使用Container.Resolve解析MainWindow,并返回做为启动窗体。

重写RegisterTypes()

重写CreateModuleCatalog()

使用XamlModuleCatalog()方法,传入URI。URI文本是当前工程的ModuleCatalog.xaml资源文件作为IModuleCatalog。

2.3ModuleCatalog.xaml

添加命名空间xmlns:m="clr-namespace:Prism.Modularity;assembly=Prism.Wpf"

修改根节点为m:ModuleCatalog,添加子节点m:ModuleInfo.并包含了ModuleA工程的信息。

<m:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="clr-namespace:Prism.Modularity;assembly=Prism.Wpf"> <m:ModuleInfo ModuleName="ModuleAModule"
ModuleType="ModuleA.ModuleAModule, ModuleA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </m:ModuleCatalog>

2.4Views下的MainWindow.xaml

包含了一个用于显示的ContentControl控件,添加了附加依赖项属性RegionName。cs代码无新增

先编译ModuleA,在运行Modules

我们看到了界面显示View A

总结:ModuleA工程引用Prism.Wpf包,通过继承自Prism.Modularity.IModule接口,并重写OnInitialized()方法获取RegionManager的对象,用来在ModuleA工程中关联显示区域Region和视图;在主工程Modules中添加Prism.Unity和ModuleA工程;

App.cs中重写CreateModuleCatalog()方法,并创建XamlModuleCatalog对象关联创建的ModuleCatalog.xaml资源文件,同时App.config中也引用ModuleA.dll配置。

ModuleCatalog.xaml资源文件设置ModuleCatalog和ModuleInfo来管理引用的Module工程。我尝试了删除App.config内容和工程,发现会报错。所以必须包含以上内容。

我们打开WPFPrismDemo工程,挑选前面5种加载方式的其中一种,写自己的加载代码。

我选择了07-Modules - Code这个示例用来加载代码;

我选择的原因是ModuleA,还是解耦后独立出来的工程,和主工程的关联关系就是主工程下引用,然后再App.cs下通过重写configureModuleCatalog()方法,加载对应的Module模块。关联关系就创建了。没有额外的操作,也不需要完整加载目录。不要参考前面的代码,如果忘记了,可以上去看一下,回忆一下你选择的加载方式,然后我们开始写:

再WPFPrismDemo工程上,新建一个类库工程ModuleSalesForecast模块,是我们的销售预测模块,用于解耦销售数据显示和销售预测显示根其他模块的重叠,主要是报表功能。

ModuleSalesForecast引用Prism.Wpf;

新建ModuleSalesForecastModule类,并继承Prism.Modularity.IModule接口.

重写OnInitialized()方法时关联SalesForecastRegion(还未定义)区域和创建的Views下的ViewSalesForecast.xaml(还未定义)。

using ModuleSalesForecast.Views;
using Prism.Ioc;
using Prism.Modularity;
using Prism.Regions; namespace ModuleSalesForecast
{
public class ModuleSalesForecastModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("SalesForecastRegion", typeof(ViewSalesForecast));
} public void RegisterTypes(IContainerRegistry containerRegistry)
{ }
}
}

新建Views文件夹

新建ViewSalesForecast.xaml

目前就放置一个TextBlock,显示为预测今年销售额全是第二。大小等于38;

ModuleSalesForecast工程部分我们目前就完成了

接下来是WPFPrismDemo部分

再WPFPrismDemo工程引用ModuleSalesForecast工程

打开App.cs

重写ConfigureModuleCatalog()方法

并调用AddModule方法,解析ModuleSalesForecastModule;

using Prism.DryIoc;using Prism.Ioc;using Prism.Modularity;using System.Windows;namespace WPFPrismDemo{    /// <summary>    /// App.xaml 的交互逻辑    /// </summary>    public partial class App : PrismApplication    {        protected override Window CreateShell()        {            return Container.Resolve<MainWindow>();        }        //这个方法如果不重写则会编译报错。        protected override void RegisterTypes(IContainerRegistry containerRegistry)        {        }        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)        {            base.ConfigureModuleCatalog(moduleCatalog);            moduleCatalog.AddModule<ModuleSalesForecast.ModuleSalesForecastModule>();        }    }}

在主窗体的MainWindow中,我们基于上一个例子,修改代码如下,增加用于显示的ContentControl ,并设置附加依赖项属性RegionName为SalesForecastRegion。

<Window x:Class="WPFPrismDemo.MainWindow"        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://prismlibrary.com/"        xmlns:local="clr-namespace:WPFPrismDemo"        mc:Ignorable="d"        Title="MainWindow" Height="450" Width="800">    <DockPanel >        <StackPanel>            <Button Content="Activate View A" Click="ActivateViewA_Click"/>            <Button Content="Deactivate View A" Click="DeactivateViewA_Click"/>            <Button Content="Activate View B" Click="ActivateViewB_Click"/>            <Button Content="Deactivate View B" Click="DeactivateViewB_Click"/>        </StackPanel>         <ContentControl prism:RegionManager.RegionName="ContentRegion" FontSize="30" VerticalAlignment="Center" HorizontalAlignment="Center"/>        <ContentControl prism:RegionManager.RegionName="SalesForecastRegion"/>    </DockPanel></Window>

运行一下我们的代码:观察结果

依次是StackPanel中的按钮,和ViewA和ViewB切换的视图,和预测分析的视图。从这一篇Modules不同的加载方式就梳理完了。

继续往后学习,07示例结束了,还有22个示例没有学习;

我创建了一个C#相关的交流群。用于分享学习资料和讨论问题。欢迎有兴趣的小伙伴:QQ群:542633085

二、从GitHub浏览Prism示例代码的方式入门WPF下的Prism之Modules的几种加载方式的更多相关文章

  1. 一、从GitHub浏览Prism示例代码的方式入门WPF下的Prism

    最近这段时间一直在看一个开源软件PowerToys的源码,里面使用Modules的开发风格让我特别着迷,感觉比我现在写代码的风格好了太多太多.我尝试把PowerToys的架构分离了出来,但是发现代码维 ...

  2. 三、从GitHub浏览Prism示例代码的方式入门WPF下的Prism之Mvvm的08-12示例

    这一篇是学习了前2篇RegionManager关联视图,和通过不同的方式加载Module示例之后的开始进入MVVM了. 从第08示例开始,进入了MVVM部分. 从08示例开始学习Prism下的MVVM ...

  3. 四、从GitHub浏览Prism示例代码的方式入门WPF下的Prism之Mvvm的13示例

    上一篇之分析了示例,没有最终写DEMO,把这一篇分析完,总结后一起写Prism下的MVVM例子. 这一篇开始分析从13示例开始,分析到MVVM主要部分结束然后写一个分析后的总结DEMO 添加一段新的内 ...

  4. 五、从GitHub浏览Prism示例代码的方式入门WPF下的Prism之MVVM中的EventAggregator

    这一篇我们主要再看完示例12.13后,写了个例子,用于再Modules下执行ApplicationCommands,使用IActiveAware执行当前View的Commands,或者Applicat ...

  5. JS window对象 返回浏览历史中的其他页面 go()方法,根据当前所处的页面,加载 history 列表中的某个具体的页面。 语法: window.history.go(number);

    返回浏览历史中的其他页面 go()方法,根据当前所处的页面,加载 history 列表中的某个具体的页面. 语法: window.history.go(number); 参数: 浏览器中,返回当前页面 ...

  6. visual studio2010中C#生成的,ArcGIS二次开发的basetool的dll,注册为COM组件tlb文件,并在arcmap中加载使用

    写了个标题好长啊~~~~ 这两天又认识了一个新玩意,记录一下下,啦啦啦~~~~~ 话说,认识arcgis快十年了,从桌面版到engine的二次开发,其实不过才认识到它的冰山一角, 它总是能带来很多还未 ...

  7. VS2017调试代码显示“当前无法命中断点,还没有为该文档加载任何符号”

    VS2017升级之后,代码调试无法进入,显示“当前无法命中断点,还没有为该文档加载任何符号”的问题解决思路: 1.工具-选项-项目和解决方案-生成并运行,取消勾选“在运行时仅生成启动项目和依赖性” 2 ...

  8. C#构造方法(函数) C#方法重载 C#字段和属性 MUI实现上拉加载和下拉刷新 SVN常用功能介绍(二) SVN常用功能介绍(一) ASP.NET常用内置对象之——Server sql server——子查询 C#接口 字符串的本质 AJAX原生JavaScript写法

    C#构造方法(函数)   一.概括 1.通常创建一个对象的方法如图: 通过  Student tom = new Student(); 创建tom对象,这种创建实例的形式被称为构造方法. 简述:用来初 ...

  9. 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性)

    一. 简介 上一个章节中,也介绍了立即加载和延迟加载,但上一个章节是针对单表而言的,不含外键,立即也好,延迟也好,都是指单表中的数据.但本章节重点介绍的三种加载方式均是针对含(导航属性.外键)的情况下 ...

随机推荐

  1. 达梦数据库产品支持技术学习分享_Week2

    本周主要从以下几个方面进行本人对达梦数据库学习的分享,学习进度和学习情况因人而异,仅供参考. 一.文本命令行工具使用的方法(Disql和dmfldr) 二.数据库备份 三.定时作业功能 四.系统表和动 ...

  2. 如何实现一个简易版的 Spring - 如何实现 AOP(下)

    前言 前面两篇 如何实现 AOP(上).如何实现 AOP(中) 做了一些 AOP 的核心基础知识简要介绍,本文进入到了实战环节了,去实现一个基于 XML 配置的简易版 AOP,虽然是简易版的但是麻雀虽 ...

  3. Go基础结构与类型05---程序运算

    package main import ( "fmt" "math" ) func main() { /*加减乘除,求余*/ fmt.Println(" ...

  4. typeof的作用及用法

    typeof的作用及用法 1.检查一个变量是否存在,是否有值. typeof在两种情况下会返回"undefined":一个变量没有被声明的时候,和一个变量的值是undefined的 ...

  5. 情景剧:C/C++中的未定义行为(undefined behavior)

    写在前面 本文尝试以情景剧的方式,轻松.直观地解释C/C++中未定义行为(undefined behavior)的概念.设计动机.优缺点等内容1,希望读者能够通过阅读本文,对undefined beh ...

  6. SLAM的通用框架:GSLAM

    SLAM的通用框架:GSLAM GSLAM: A General SLAM Framework and Benchmark 论文链接: http://openaccess.thecvf.com/con ...

  7. Linux 2 的 Windows 子系统上发布 CUDA

    Linux 2 的 Windows 子系统上发布 CUDA 为响应大众需求,微软 宣布 在 2020 年 5 月的 建造 大会上推出了 建造 ( WSL 2 ) – GPU 加速功能.这一特性为许多计 ...

  8. CVPR2020:端到端学习三维点云的局部多视图描述符

    CVPR2020:端到端学习三维点云的局部多视图描述符 End-to-End Learning Local Multi-View Descriptors for 3D Point Clouds 论文地 ...

  9. MySQL笔记04(黑马)

    今日内容 多表查询 事务 DCL 多表查询 * 查询语法: select 列名列表 from 表名列表 where.... * 准备sql # 创建部门表 CREATE TABLE dept( id ...

  10. Java 到底是值传递还是引用传递?

    关于这个问题,引发过很多广泛的讨论,看来很多程序员对于这个问题的理解都不尽相同,甚至很多人理解的是错误的.还有的人可能知道Java中的参数传递是值传递,但是说不出来为什么. 在开始深入讲解之前,有必要 ...