WPF+Prism框架下实现Application类多层继承复用的问题
刚好我最近在WPF+Prism项目里做了几乎一模一样的抽象复用,给你一套落地性很强的方案,完美匹配你想要的继承结构,还能把所有公共逻辑、资源、服务都抽离出来:
核心思路
把所有通用逻辑(Prism初始化、公共资源、共享服务/模块)封装到抽象的BaseApp中,具体应用只需要继承它并实现少量特定逻辑(注册自身模块/服务),完全符合你要的Application <-- BaseApp(抽象) <-- MySpecificApplication结构。
分步实现
1. 创建抽象的BaseApp(继承PrismApplication)
Prism本身提供了PrismApplication来替代原生WPF的Application,我们的抽象基类直接继承它,把所有公共逻辑都塞在这里:
using Prism.Ioc; using Prism.Modularity; using Prism.Regions; using System.Windows; public abstract class BaseApp : PrismApplication { // 公共资源字典的路径,根据你的公共程序集调整 private const string GlobalSharedResources = "/YourCommonAssembly;component/Resources/GlobalStyles.xaml"; // 公共Shell:所有应用共用的主窗口(包含Prism区域) protected override Window CreateShell() { return Container.Resolve<MainShell>(); // MainShell放在公共程序集里 } // 公共服务注册:所有应用都需要的服务 protected virtual void RegisterSharedServices(IContainerRegistry containerRegistry) { containerRegistry.RegisterSingleton<ICommonAuthService, CommonAuthService>(); containerRegistry.RegisterSingleton<IRegionAdapterMappings, RegionAdapterMappings>(); // 其他公共服务... } // 公共模块注册:所有应用都要加载的模块 protected virtual void ConfigureSharedModules(IModuleCatalog moduleCatalog) { moduleCatalog.AddModule<CommonNavigationModule>(); moduleCatalog.AddModule<CommonSettingsModule>(); // 其他公共模块... } // 加载全局公共资源 private void LoadSharedResources() { var sharedDict = new ResourceDictionary { Source = new Uri(GlobalSharedResources, UriKind.RelativeOrAbsolute) }; Application.Current.Resources.MergedDictionaries.Add(sharedDict); } // 留给子类实现的抽象方法:注册当前应用特有的服务 protected abstract void RegisterSpecificServices(IContainerRegistry containerRegistry); // 留给子类实现的抽象方法:配置当前应用特有的模块(负责不同区域的内容) protected abstract void ConfigureSpecificModules(IModuleCatalog moduleCatalog); // 重写Prism的注册逻辑:先公共,再特定 sealed override void RegisterTypes(IContainerRegistry containerRegistry) { RegisterSharedServices(containerRegistry); RegisterSpecificServices(containerRegistry); } // 重写Prism的模块配置:先公共,再特定 sealed override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) { ConfigureSharedModules(moduleCatalog); ConfigureSpecificModules(moduleCatalog); } // 初始化Shell后加载公共资源 protected override void InitializeShell(Window shell) { base.InitializeShell(shell); LoadSharedResources(); } }
2. 实现具体应用的MySpecificApplication
具体应用只需要继承BaseApp,实现两个抽象方法,注册自己的专属服务和模块(这些模块就是负责加载不同Prism区域内容的核心):
using Prism.Ioc; using Prism.Modularity; public partial class MySpecificApplication : BaseApp { // 注册当前应用特有的服务 protected override void RegisterSpecificServices(IContainerRegistry containerRegistry) { containerRegistry.Register<ISpecificBusinessService, SpecificBusinessService>(); } // 配置当前应用特有的模块:这些模块会向Prism区域注册各自的视图 protected override void ConfigureSpecificModules(IModuleCatalog moduleCatalog) { moduleCatalog.AddModule<SalesDashboardModule>(); // 负责加载销售区域的内容 moduleCatalog.AddModule<CustomerManagementModule>(); // 负责加载客户管理区域的内容 } }
3. 调整具体应用的App.xaml
WPF的App.xaml需要指向我们的MySpecificApplication,并且移除StartupUri(因为Prism会通过CreateShell自动加载主窗口):
<base:BaseApp x:Class="YourSpecificApp.MySpecificApplication" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:base="clr-namespace:YourCommonAssembly.AppCore;assembly=YourCommonAssembly"> <!-- 这里可以添加当前应用特有的资源,会自动覆盖公共资源中的同名项 --> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <!-- 可选:添加当前应用专属的资源字典 --> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </base:BaseApp>
关键注意事项
- 公共程序集隔离:把
BaseApp、MainShell、公共服务/模块都放在单独的类库中,所有具体应用引用这个类库即可。 - 区域内容差异化:不同应用的区域内容完全通过各自的模块实现,模块内部使用
IRegionManager向指定区域注册视图,完全不影响公共逻辑。 - 资源优先级:具体应用的资源会覆盖公共资源中的同名资源,满足个性化需求的同时不破坏复用性。
- Prism生命周期兼容:所有逻辑都遵循Prism的生命周期,不会出现初始化顺序问题,比如资源加载放在
InitializeShell确保Shell已经初始化完成。
内容的提问来源于stack exchange,提问作者J4N
相关产品推荐
相关产品推荐

