这一篇梳理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. .Net Core gRPC 实战(一)

    gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架. gRPC 的主要优点是: 现代高性能轻量级 RPC 框架. 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现. 可用 ...

  2. Python+Selenium自动化-定位页面元素的八种方法

    Python+Selenium自动化-定位页面元素的八种方法   本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子. 0.元素定位方法主要有: id定位:find_elemen ...

  3. 噪声标签的负训练:ICCV2019论文解析

    噪声标签的负训练:ICCV2019论文解析 NLNL: Negative Learning for Noisy Labels 论文链接: http://openaccess.thecvf.com/co ...

  4. SLAM相机定位

    SLAM相机定位 摘要 深度学习在相机定位方面取得了很好的结果,但是当前的单幅图像定位技术通常会缺乏鲁棒性,从而导致较大的离群值.在某种程度上,这已通过序列的(多图像)或几何约束方法解决,这些方法可以 ...

  5. 活动识别API服务开发

    活动识别API服务开发 要使用华为活动识别服务API,需要确保设备已经下载并安装了HMS Core(APK),并将Location Kit的SDK集成到项目中. 指定应用权限 在Android Q以下 ...

  6. Minkowski坐标管理

    Minkowski坐标管理 坐标键 classMinkowskiEngine.CoordsKey(D) __init__(D) 初始化self. See help(type(self))有关准确的签名 ...

  7. spring 声明式事务剖析

    spring事务是在数据库事务的基础上进行封装扩展, 支持原有事务的隔离级别, 加入了事务传播的概念,提供多个事务合并和分割的功能, 提供声明式事务,让事务和业务代码分开 spring提供了三个接口供 ...

  8. Headline 项目总结中

    目录 1.项目准备 1.1 rem适配 1.2 通用样式CSS 1.3删除测试代码 1.4Git托管 2.login页面 2.1 页面布局和表单校验 2.2login页的接口抽取 2.5.loadin ...

  9. 【NX二次开发】 获取体的面 UF_MODL_ask_body_faces

    获取体的面 1 extern DllExport void ufsta(char *param, int *returnCode, int rlen) 2 { 3 UF_initialize(); 4 ...

  10. 『心善渊』Selenium3.0基础 — 7、XPath轴定位详解

    目录 1.XPath轴定位介绍 2.位置路径表达式概念 3.步的路径表达式范例 4.练习 使用XPath轴方式,可根据文档中元素的相对位置,来进行元素的定位.例如:先找到一个相对好定位的元素,在根据与 ...