0x4Modules
Modules是能够独立开发、测试、部署的功能单元,Modules可以被设计成实现特定业务逻辑的模块(如Profile Management),也可以被设计成实现通用基础设施或服务的模块(如Logging、Exception Management)。
既然Modules能够独立开发、测试、部署,那么如何告诉Shell(我们的宿主程序)去Load哪些Module,以怎样的形式Load这些Module呢?Prism为此提供了一个叫ModuleCatalog的东西。他用这个来管理Module。所以在App启动之初,需要创建配置一个ModuleCatalog。
[7.1updated]Prism.Modularity在7.1中也改了很多,主要是为了统一api吧,我们就看对wpf的影响:
- 在IModule 接口中移除了Initialize()
- 新增了两个方法
// // Summary: // Notifies the module that it has be initialized. void OnInitialized(IContainerProvider containerProvider); // // Summary: // Used to register types with the container that will be used by your application. void RegisterTypes(IContainerRegistry containerRegistry);
如果升级7.1的话,需要修改所有 IModule 的实现,移除Initialize(),并且实现新接口,这样一来,你将不再从 构造函数中获取module的依赖,而是直接从IContainerProvider获取,接下来的代码,我将更新到7.1,并且尽量说明其中的变动。
✏: 先新增一个WpfApp项目,命名ModuleA,删除App.config和App.xaml,然后将outputType改为Class Library。在Views文件夹下面新建一个用户控件ViewA
新增一个类ModuleAModule.cs
实现IModule接口(每一个Module类都要实现这个接口,而每一个Module都要有这样一个类来对Module里的资源统一管理)
using ModuleA.Views;using Prism.Ioc;using Prism.Modularity;using Prism.Regions;namespace ModuleA{ public class ModuleAModule : IModule { public void OnInitialized(IContainerProvider containerProvider) { var regionManager = containerProvider.Resolve(); regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA)); } public void RegisterTypes(IContainerRegistry containerRegistry) { } }}
OnInitialized实现的时候,顺便将一个viewA与ContentRegion进行关联,看代码
var regionManager = containerProvider.Resolve(); regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
[7.1updated]记得之前是怎么写的吗?regionManager 是通过构造函数注入的,现在,不需要了,而是直接从containerProvider中解析。
那么,ModuleCatalog是怎样让Shell加载ModuleA的呢?,,ԾㅂԾ,,
代码
先在shell所在module添加ModuleA引用,然后:
~~Bootstrapper.cs
中重写ConfigureModuleCatalog
:
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) { moduleCatalog.AddModule(); }
啊妹子,炒鸡简单有没有?
配置文件
~~Bootstrapper.cs
中重写CreateModuleCatalog
:
[7.1updated]App.xaml.cs中重写CreateModuleCatalog
protected override IModuleCatalog CreateModuleCatalog() { return new ConfigurationModuleCatalog(); }
这表示,ModuleCatalog将从配置文件中创建。
App.config中添加了节点,并且指定了需要Load的module,并且设置了startupLoaded参数来告诉shell,是否在启动时就加载他。下面是App.config的内容,他加载了一个名为ModuleAModule的Module,存在ModuleA.dll。
通过配置文件来配置ModuleCatalog就不需要添加ModuleA引用了
Directory
重写IModuleCatalog 方法:
[7.1Updated] ModulePath 就是你需要加载的module的dll生成目录protected override IModuleCatalog CreateModuleCatalog() { return new DirectoryModuleCatalog() { ModulePath = @".\Modules" }; }
LoadManual
重写ConfigureModuleCatalog方法:
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) { var moduleAType = typeof(ModuleAModule); moduleCatalog.AddModule(new ModuleInfo() { ModuleName = moduleAType.Name, ModuleType = moduleAType.AssemblyQualifiedName, InitializationMode = InitializationMode.OnDemand }); }
上面的只是几种加载 module的方式,不做深入的研究了,反正能用就行了,蛮喜欢用 config的模式的
[7.1updated]从代码片段上看,这里最大的变动就是IModule了,还有就是ConfigureModuleCatalog的时候用到了IModuleCatalog (容器管理?)