1. Prism框架简介
Prism是一个用于构建松散耦合、可测试和可维护的WPF桌面应用程序的框架。它最初由微软模式与实践团队开发,现在由社区维护,是构建企业级WPF应用程序的首选框架之一。
Prism框架的核心优势:
- 模块化设计:将应用程序分解为独立的功能模块
- 松散耦合:通过依赖注入和事件聚合器实现组件间的松散耦合
- MVVM模式支持:提供完整的MVVM(Model-View-ViewModel)实现
- 导航框架:简化视图间的导航
- 区域管理:支持动态UI组合
- 命令模式:提供强大的命令绑定机制
2. Prism核心组件
2.1 模块化系统
Prism的模块化系统允许开发人员将应用程序分解为独立的功能模块,每个模块可以单独开发、测试和部署。
csharp
// 模块定义示例
public class CustomerModule : IModule
{
private readonly IRegionManager _regionManager;
public CustomerModule(IRegionManager regionManager)
{
_regionManager = regionManager;
}
public void OnInitialized(IContainerProvider containerProvider)
{
// 在区域中注册视图
_regionManager.RegisterViewWithRegion("MainRegion", typeof(CustomerView));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
// 注册服务和视图
containerRegistry.RegisterSingleton<ICustomerService, CustomerService>();
containerRegistry.RegisterForNavigation<CustomerDetailView>();
}
}
2.2 依赖注入容器
Prism支持多种依赖注入容器,包括Unity、DryIoc和Autofac。依赖注入是实现松散耦合的关键机制。
csharp
// 应用程序启动配置
protected override void ConfigureContainer()
{
// 注册类型到DI容器
Container.RegisterType<IOrderService, OrderService>(new ContainerControlledLifetimeManager());
Container.RegisterType<ICustomerRepository, CustomerRepository>();
}
2.3 区域管理器
区域管理器允许在预定义的UI区域中动态加载和卸载视图,是实现模块化UI的核心组件。
csharp
// 在XAML中定义区域
<ContentControl prism:RegionManager.RegionName="MainRegion" />
// 在代码中导航到区域
_regionManager.RequestNavigate("MainRegion", "CustomerView");
2.4 事件聚合器
事件聚合器提供了一种发布-订阅机制,允许模块之间进行通信而无需直接引用。
csharp
// 定义事件
public class CustomerUpdatedEvent : PubSubEvent<CustomerModel> { }
// 发布事件
_eventAggregator.GetEvent<CustomerUpdatedEvent>().Publish(updatedCustomer);
// 订阅事件
_eventAggregator.GetEvent<CustomerUpdatedEvent>()
.Subscribe(OnCustomerUpdated, ThreadOption.UIThread, false,
customer => customer.Id == currentCustomerId);
3. MVVM模式实现
Prism提供了完整的MVVM实现,包括BindableBase基类、DelegateCommand和导航服务。
3.1 BindableBase
BindableBase类实现了INotifyPropertyChanged接口,简化了属性变更通知。
csharp
public class CustomerViewModel : BindableBase
{
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
private bool _isActive;
public bool IsActive
{
get => _isActive;
set => SetProperty(ref _isActive, value,
() => RaisePropertyChanged(nameof(StatusDisplay)));
}
public string StatusDisplay => IsActive ? "活跃" : "非活跃";
}
3.2 DelegateCommand
DelegateCommand提供了命令模式的实现,支持命令执行条件和命令状态更新。
csharp
public class OrderViewModel : BindableBase
{
private readonly IOrderService _orderService;
private Order _currentOrder;
public DelegateCommand SubmitOrderCommand { get; private set; }
public OrderViewModel(IOrderService orderService)
{
_orderService = orderService;
SubmitOrderCommand = new DelegateCommand(ExecuteSubmitOrder, CanSubmitOrder)
.ObservesProperty(() => CurrentOrder.IsValid);
}
private bool CanSubmitOrder()
{
return CurrentOrder != null && CurrentOrder.IsValid;
}
private void ExecuteSubmitOrder()
{
_orderService.SubmitOrder(CurrentOrder);
}
public Order CurrentOrder
{
get => _currentOrder;
set => SetProperty(ref _currentOrder, value);
}
}
4. 导航框架
Prism的导航框架简化了视图之间的导航,支持导航参数和导航回调。
csharp
// 注册导航
containerRegistry.RegisterForNavigation<ProductDetailView>("ProductDetail");
// 执行导航
_navigationService.NavigateAsync("ProductDetail?id=123",
new NavigationParameters
{
{ "category", "electronics" }
});
// 在目标ViewModel中接收参数
public override void OnNavigatedTo(INavigationParameters parameters)
{
if (parameters.ContainsKey("id"))
{
string productId = parameters.GetValue<string>("id");
LoadProduct(productId);
}
}
5. 对话框服务
Prism提供了对话框服务,用于显示模态和非模态对话框。
csharp
// 注册对话框
containerRegistry.RegisterDialog<ConfirmationDialog, ConfirmationDialogViewModel>();
// 显示对话框
_dialogService.ShowDialog("ConfirmationDialog",
new DialogParameters
{
{ "title", "确认删除" },
{ "message", "确定要删除此项目吗?" }
},
r =>
{
if (r.Result == ButtonResult.OK)
{
DeleteItem();
}
});
6. 实际应用示例
下面是一个简单的Prism应用程序结构示例:
MyPrismApp/
├── MyPrismApp.Core/ # 核心库,包含共享接口和模型
├── MyPrismApp.Modules.Orders/ # 订单模块
├── MyPrismApp.Modules.Customers/ # 客户模块
├── MyPrismApp.Modules.Products/ # 产品模块
└── MyPrismApp/ # 主应用程序
├── App.xaml
├── App.xaml.cs
└── Shell.xaml # 主窗口
6.1 应用程序启动类
csharp
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<Shell>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IApplicationSettingsService, ApplicationSettingsService>();
containerRegistry.RegisterSingleton<IThemeService, ThemeService>();
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
// 注册模块
moduleCatalog.AddModule<CustomersModule>();
moduleCatalog.AddModule<OrdersModule>();
moduleCatalog.AddModule<ProductsModule>();
}
}
6.2 Shell视图
xml
<Window x:Class="MyPrismApp.Views.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
Title="Prism应用示例" Height="600" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 顶部菜单 -->
<Menu Grid.Row="0">
<MenuItem Header="文件">
<MenuItem Header="退出" Command="{Binding ExitCommand}"/>
</MenuItem>
<MenuItem Header="客户" Command="{Binding NavigateCommand}"
CommandParameter="Customers"/>
<MenuItem Header="订单" Command="{Binding NavigateCommand}"
CommandParameter="Orders"/>
<MenuItem Header="产品" Command="{Binding NavigateCommand}"
CommandParameter="Products"/>
</Menu>
<!-- 主内容区域 -->
<ContentControl Grid.Row="1" prism:RegionManager.RegionName="MainRegion" />
<!-- 状态栏 -->
<StatusBar Grid.Row="2">
<TextBlock Text="{Binding StatusMessage}" />
</StatusBar>
</Grid>
</Window>
7. 最佳实践
7.1 模块设计原则
- 每个模块应该是自包含的,拥有自己的视图、视图模型和服务
- 模块之间通过接口和事件聚合器通信,避免直接引用
- 共享功能应放在核心模块中
7.2 性能优化
- 使用按需加载模块,减少启动时间
- 合理使用CompositeCommand,避免过多的命令绑定
- 优化区域管理器的视图切换
csharp
// 配置按需加载模块
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
// 启动时加载
moduleCatalog.AddModule<CoreModule>();
// 按需加载
moduleCatalog.AddModule(typeof(ReportsModule).Name,
typeof(ReportsModule).AssemblyQualifiedName,
InitializationMode.OnDemand);
}
7.3 测试策略
Prism的松散耦合设计使得单元测试变得简单:
csharp
[TestMethod]
public void CanExecuteSubmitOrder_WithValidOrder_ReturnsTrue()
{
// Arrange
var orderServiceMock = new Mock<IOrderService>();
var viewModel = new OrderViewModel(orderServiceMock.Object);
var order = new Order { IsValid = true };
viewModel.CurrentOrder = order;
// Act
bool canExecute = viewModel.SubmitOrderCommand.CanExecute();
// Assert
Assert.IsTrue(canExecute);
}
8. 与其他框架的比较
特性 | Prism | MVVM Light | Caliburn.Micro |
---|---|---|---|
模块化 | ✓ | ✗ | 部分支持 |
依赖注入 | ✓ | 部分支持 | ✓ |
区域管理 | ✓ | ✗ | ✗ |
事件聚合器 | ✓ | ✓ | ✓ |
导航框架 | ✓ | 部分支持 | ✓ |
对话框服务 | ✓ | ✗ | ✓ |
学习曲线 | 中等 | 低 | 高 |
社区支持 | 活跃 | 一般 | 一般 |
9. 总结
Prism框架是构建企业级WPF应用程序的强大工具,它提供了模块化、松散耦合和MVVM支持等关键特性。通过使用Prism,开发人员可以创建可维护、可测试和可扩展的应用程序。
虽然Prism有一定的学习曲线,但其提供的功能和架构优势使其成为大型WPF应用程序开发的理想选择。对于需要构建复杂、模块化桌面应用的团队来说,投资学习Prism将带来长期的收益。