索引
【翻译】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); }
关键类
(略)
这个系列含金量不高啊