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<IRegionManager>();
regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
}
OnInitialized實現的時候,順便將一個viewA與ContentRegion進行關聯,看代碼
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
[7.1updated]記得之前是怎么寫的嗎?regionManager 是通過構造函數注入的,現在,不需要了,而是直接從containerProvider中解析。
那么,ModuleCatalog是怎樣讓Shell加載ModuleA的呢?,,ԾㅂԾ,,
代碼
先在shell所在module添加ModuleA引用,然后:
[7.1updated]App.xaml.cs中重寫ConfigureModuleCatalog
```c#
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<ModuleA.ModuleAModule>();
}
```
啊妹子,炒雞簡單有沒有?
#### 配置文件
~~~`Bootstrapper.cs`中重寫`CreateModuleCatalog`:~~~
[7.1updated]App.xaml.cs中重寫CreateModuleCatalog
```C#
protected override IModuleCatalog CreateModuleCatalog()
{
return new ConfigurationModuleCatalog();
}
```
這表示,ModuleCatalog將從配置文件中創建。
App.config中添加了<modules>節點,並且指定了需要Load的module,並且設置了startupLoaded參數來告訴shell,是否在啟動時就加載他。下面是App.config的內容,他加載了一個名為ModuleAModule的Module,存在ModuleA.dll。
```xml-dtd
<?xml version="1.0" encoding="utf-8"?>
<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>
```
*通過配置文件來配置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 (容器管理?)
