这一篇梳理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. 关于LSTM核心思想的部分理解

    具体资料可以查阅网上,这里提到一些难理解的点.别人讲过的知识点我就不重复了. LSTM 的关键就是细胞状态,按照水平线从左向右运行,如同履带,在整个链上运行. 根据时间t-1,t,t+1,我们可以看出 ...

  2. 前端基础——js数据类型及判断方法

    一.数据类型 我们通常熟知的数据类型有六种,包括5种基本数据类型(Number, String, Boolean, Undefined, Null)和一种引用数据类型(Object).ES6又新增了一 ...

  3. TVMNN编译Compiler栈

    TVMNN编译Compiler栈 内容纲要 前言 调研目标 TVM介绍 TVM源码架构 FrontEnd Relay BackEnd VTA实现原理及设计思想提炼 整体结构 VTA Hardware ...

  4. OpenCV读写视频文件解析

    OpenCV读写视频文件解析 一.视频读写类 视频处理的是运动图像,而不是静止图像.视频资源可以是一个专用摄像机.网络摄像头.视频文件或图像文件序列. 在 OpenCV 中,VideoCapture ...

  5. 运用iGuard防御ADS权限维持

    权限维持是一门庞大的学问,当攻击者在入侵服务器获得主机权限后,往往会想尽办法隐藏其入侵途径以维持权限.权限维持的一般手段包括构造文件包含漏洞.构造远程任意代码执行漏洞.构造SQL注入点.利用系统自启动 ...

  6. DHCP的原理与配置

    DHCP 动态主机配置协议(Dynamic Host Configuration Protocol) 可以减少管理员的工作量 避免用户手工配置网络参数时造成的地址冲突 DHCP报文类型: 报文类型   ...

  7. NX二次开发】Block UI 选择特征

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  8. nacos 集群搭建

    nacos 集群搭建 1.单机部署 从nacos官网下载zip/tar包,https://github.com/alibaba/nacos/releases/tag/2.0.2 解压后即可启动 外置数 ...

  9. 一篇文章带你吃透,Java界最神秘技术ClassLoader

    ClassLoader 是 Java 届最为神秘的技术之一,无数人被它伤透了脑筋,摸不清门道究竟在哪里.网上的文章也是一篇又一篇,经过本人的亲自鉴定,绝大部分内容都是在误导别人.本文我带读者彻底吃透 ...

  10. sql优化问题

    一.分析阶段 一 般来说,在系统分析阶段往往有太多需要关注的地方,系统各种功能性.可用性.可靠性.安全性需求往往吸引了我们大部分的注意力,但是,我们必须注意,性能 是很重要的非功能性需求,必须根据系统 ...