索引
【翻譯】WPF應用程序模塊化開發快速入門(使用Prism框架)【上】
【翻譯】WPF應用程序模塊化開發快速入門(使用Prism+MEF)【中】
系統啟動
系統使用Bootstrapper類型來啟動程序,並初始化主窗口
/// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); // The boostrapper will create the Shell instance, so the App.xaml does not have a StartupUri. QuickStartBootstrapper bootstrapper = new QuickStartBootstrapper(); bootstrapper.Run(); } }
QuickStartBootstrapper類型繼承自MefBootstrapper類型
為了創建和顯示主窗口,此類型重寫了CreateShell和InitializeShell方法
protected override DependencyObject CreateShell() { return this.Container.GetExportedValue<Shell>(); }
protected override void InitializeShell() { base.InitializeShell(); Application.Current.MainWindow = (Shell) this.Shell; Application.Current.MainWindow.Show(); }
創建模塊
在此快速入門示例中
創建了六個模塊
這些模塊都實現了IModule接口
添加了相關的特性
選擇了依賴屬性
[ModuleExport(typeof(ModuleA), DependsOnModuleNames = new string[] { "ModuleD" })] public class ModuleA : IModule
當使用MEF框架的時候
ModuleExport特性允許MEF發現適當的、
繼承自IModule接口的類型。
此外:它還支持詳細說明額外模塊的元數據
注冊模塊
在快速入門示例中
系統直接引用了一些模塊
通過監控目錄發現了一些模塊
還有一些模塊是通過配置文件加載的
QuickStartBootstrapper類型還重寫了
CreateModuleCatalog和ConfigureModuleCatalog方法
這樣就可以通過配置文件來注冊模塊
使用MEF時
AggregateCatalog支持發現模塊和類型
基於此,
QuickStartBootstrapper重寫ConfigureAggregateCatalog
模版方法並使用MEF注冊程序集
仍然使用ModuleCatalog加載配置文件來注冊模塊
protected override IModuleCatalog CreateModuleCatalog() { // When using MEF, the existing Prism ModuleCatalog is still the place to configure modules via configuration files. return new ConfigurationModuleCatalog(); }
protected override void ConfigureAggregateCatalog() { base.ConfigureAggregateCatalog(); // Add this assembly to export ModuleTracker this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(QuickStartBootstrapper).Assembly)); // Module A is referenced in in the project and directly in code. this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ModuleA).Assembly)); this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ModuleC).Assembly)); // Module B and Module D are copied to a directory as part of a post-build step. // These modules are not referenced in the project and are discovered by inspecting a directory. // Both projects have a post-build step to copy themselves into that directory. DirectoryCatalog catalog = new DirectoryCatalog("DirectoryModules"); this.AggregateCatalog.Catalogs.Add(catalog); }
加載模塊
在此快速入門中
即有在系統啟動時加載模塊的業務
也有按需加載模塊的業務
還有顯示進度、控制模塊間的依賴性等業務
注意:
此快速入門示例還有一些額外的類
以幫助追蹤模塊初始化的狀態信息
這些類主要是起了示范的目的
Shell的用戶界面里包含了六個ModuleControl
Shell的DataContext是ModuleTracker
ModuleTracker類型為每個模塊保存一個ModuleTrackingState
ModuleTrackingState綁定到與之對應的ModuleControl
ModuleControl使用一個默認的樣式來展現模塊的加載和初始化狀態
當點擊ModuleControl自定義控件的時候
將觸發如下事件:
/// <summary> /// Handles the RequestModuleLoad event of the ModuleC control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void ModuleC_RequestModuleLoad(object sender, EventArgs e) { // The ModuleManager uses the Async Events Pattern. this.moduleManager.LoadModule(WellKnownModuleNames.ModuleC); }
此事件被觸發的時候會同時觸發moduleManager的ModuleDownloadProgressChanged事件
此事件是在shell頁面的OnImportsSatisfied方法中被注冊的
this.moduleManager.LoadModuleCompleted += this.ModuleManager_LoadModuleCompleted; this.moduleManager.ModuleDownloadProgressChanged += this.ModuleManager_ModuleDownloadProgressChanged;
/// <summary> /// Handles the LoadModuleProgressChanged event of the ModuleManager control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="Microsoft.Practices.Composite.Modularity.ModuleDownloadProgressChangedEventArgs"/> instance containing the event data.</param> private void ModuleManager_ModuleDownloadProgressChanged(object sender, ModuleDownloadProgressChangedEventArgs e) { this.moduleTracker.RecordModuleDownloading(e.ModuleInfo.ModuleName, e.BytesReceived, e.TotalBytesToReceive); }
當模塊加載完成后
shell頁面也會被通知到
/// <summary> /// Handles the LoadModuleCompleted event of the ModuleManager control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="Microsoft.Practices.Composite.Modularity.LoadModuleCompletedEventArgs"/> instance containing the event data.</param> private void ModuleManager_LoadModuleCompleted(object sender, LoadModuleCompletedEventArgs e) { this.moduleTracker.RecordModuleLoaded(e.ModuleInfo.ModuleName); }
關鍵類
(略)
這個系列含金量不高啊