WPF Prism 框架完全入门指南:从环境搭建到弹窗导航实战
-
- 前言
- [一、Prism 框架概述](#一、Prism 框架概述)
-
- [1.1 什么是 Prism](#1.1 什么是 Prism)
- [1.2 为什么选择 Prism](#1.2 为什么选择 Prism)
- [二、环境搭建与第一个 Prism 应用](#二、环境搭建与第一个 Prism 应用)
-
- [2.1 创建项目并安装 NuGet 包](#2.1 创建项目并安装 NuGet 包)
- [2.2 改造 App.xaml](#2.2 改造 App.xaml)
- [2.3 实现必要方法](#2.3 实现必要方法)
- [2.4 项目结构约定](#2.4 项目结构约定)
- [三、MVVM 模式在 Prism 中的实现](#三、MVVM 模式在 Prism 中的实现)
-
- [3.1 BindableBase 与属性变更通知](#3.1 BindableBase 与属性变更通知)
- [3.2 DelegateCommand 命令绑定](#3.2 DelegateCommand 命令绑定)
- [3.3 ViewModelLocator 自动绑定](#3.3 ViewModelLocator 自动绑定)
- 四、区域与导航系统
-
- [4.1 区域(Region)概念](#4.1 区域(Region)概念)
- [4.2 视图发现与视图注入](#4.2 视图发现与视图注入)
- [4.3 基于 URI 的导航](#4.3 基于 URI 的导航)
- [4.4 INavigationAware 接口](#4.4 INavigationAware 接口)
- [4.5 导航日志](#4.5 导航日志)
- 五、对话框服务
-
- [5.1 传统弹窗的问题](#5.1 传统弹窗的问题)
- [5.2 实现 IDialogAware 接口](#5.2 实现 IDialogAware 接口)
- [5.3 注册与使用对话框](#5.3 注册与使用对话框)
- [5.4 自定义对话框窗口样式](#5.4 自定义对话框窗口样式)
- 六、完整示例:一个简单的员工管理系统
-
- [6.1 项目结构](#6.1 项目结构)
- [6.2 关键代码实现](#6.2 关键代码实现)
- 七、最佳实践与注意事项
-
- [7.1 服务生命周期管理](#7.1 服务生命周期管理)
- [7.2 模块化开发建议](#7.2 模块化开发建议)
- [7.3 注意事项](#7.3 注意事项)
- 八、总结
前言
在 WPF 桌面应用开发中,随着项目规模的增长,如果没有良好的架构设计,代码很快就会变得难以维护------视图与逻辑紧密耦合、模块间相互依赖、测试困难等问题会接踵而至。Prism 正是为了解决这些问题而生的 MVVM 框架。
Prism 最初由微软 Patterns & Practices 团队开发,后转为开源社区维护,至今已有十余年历史。它提供了一套完整的设计模式实现,包括依赖注入、模块化、导航、事件聚合等核心功能,能够帮助开发者构建松耦合、可测试、可维护的 XAML 应用程序。
本文将从零开始,带你系统地掌握 Prism 的核心概念与实战技巧,涵盖环境搭建、MVVM 实现、区域导航、弹窗服务等日常开发中最常用的功能。
一、Prism 框架概述
1.1 什么是 Prism
Prism 是一个用于构建 XAML 应用的 MVVM 框架,支持 WPF、.NET MAUI、Uno Platform 和 Xamarin Forms 等平台。它的核心功能通过 .NET Standard 共享库实现,各平台特定的功能则在相应的库中实现。
Prism 主要提供以下能力:
- MVVM 基础设施:BindableBase 基类、DelegateCommand 命令封装
- 依赖注入:统一的 IContainerRegistry 接口,支持 Unity、DryIoc 等容器
- 区域管理:将 UI 拆分为多个区域,实现视图的动态加载与切换
- 模块化:将应用分解为独立模块,支持按需加载
- 导航系统:基于 URI 的视图导航,支持参数传递与导航日志
- 对话框服务:MVVM 模式下的弹窗解决方案
- 事件聚合器:组件间松耦合的消息通信机制
1.2 为什么选择 Prism
相比 MVVM Light、Caliburn.Micro 等其他 MVVM 框架,Prism 的优势在于:
- 功能全面:不仅提供 MVVM 基础能力,还涵盖模块化、区域导航等企业级功能
- 生态成熟:微软官方背景,文档完善,社区活跃
- 容器无关:通过统一接口支持多种 IoC 容器
- 平台统一:核心逻辑可跨平台复用
二、环境搭建与第一个 Prism 应用
2.1 创建项目并安装 NuGet 包
首先,在 Visual Studio 中创建一个 WPF 应用程序项目(.NET 6/7/8 均可)。然后安装 Prism 相关的 NuGet 包。
Prism 支持多种 IoC 容器,常用的是 Unity 和 DryIoc,选择其一即可:
| Package | 容器 | 说明 |
|---|---|---|
| Prism.Unity | Unity | 经典选择,下载量最高 |
| Prism.DryIoc | DryIoc | 性能更优,轻量级 |
通过 NuGet 包管理器或程序包管理器控制台安装:
powershell
Install-Package Prism.Unity
提示:安装 Prism.Unity 会自动引入 Prism.Core 和 Prism.Wpf,无需单独安装其他依赖。
2.2 改造 App.xaml
将标准 WPF 的 Application 类替换为 Prism 的 PrismApplication:
App.xaml:
xml
<prism:PrismApplication
x:Class="PrismDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PrismDemo"
xmlns:prism="http://prismlibrary.com/">
<Application.Resources>
</Application.Resources>
</prism:PrismApplication>
注意 :务必删除
StartupUri属性,否则会导致两个窗口实例被创建。
2.3 实现必要方法
App.xaml.cs:
csharp
using System.Windows;
using Prism.Ioc;
using Prism.Unity;
using PrismDemo.Views;
namespace PrismDemo
{
public partial class App : PrismApplication
{
// 创建应用程序的主窗口(Shell)
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
// 注册应用程序中使用的类型和服务
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// 这里暂时为空,后续会添加注册内容
}
}
}
CreateShell 方法通过 IoC 容器解析并返回主窗口实例,RegisterTypes 方法用于注册应用中的服务与依赖。至此,一个最简 Prism 应用已搭建完成。
2.4 项目结构约定
Prism 推荐(但不强制)以下目录结构:
PrismDemo/
├── Views/ # 视图文件(Window、UserControl)
├── ViewModels/ # 视图模型文件
├── Models/ # 数据模型
├── Services/ # 服务接口与实现
└── Controls/ # 自定义控件
这种约定有助于 ViewModelLocator 自动匹配视图与视图模型。
三、MVVM 模式在 Prism 中的实现
3.1 BindableBase 与属性变更通知
Prism 提供了 BindableBase 作为 ViewModel 的基类,它实现了 INotifyPropertyChanged 接口,并提供了 SetProperty 方法简化属性变更通知:
csharp
using Prism.Mvvm;
using System.Collections.ObjectModel;
namespace PrismDemo.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Demo Application";
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
private string _selectedItem;
public string SelectedItem
{
get => _selectedItem;
set
{
if (SetProperty(ref _selectedItem, value))
{
// 当选中的项变化时执行的额外逻辑
OnSelectedItemChanged();
}
}
}
public ObservableCollection<string> Items { get; set; } =
new ObservableCollection<string>();
private void OnSelectedItemChanged()
{
// 处理选中项变化
}
}
}
SetProperty 方法会检查新旧值是否相等,仅在值变化时触发 PropertyChanged 事件,并返回 bool 值指示是否发生了变化。
3.2 DelegateCommand 命令绑定
Prism 使用 DelegateCommand 实现 ICommand 接口,支持带参数和不带参数的命令,以及执行条件判断:
csharp
using Prism.Commands;
public class MainWindowViewModel : BindableBase
{
// 无参数命令
private DelegateCommand _loadCommand;
public DelegateCommand LoadCommand =>
_loadCommand ?? (_loadCommand = new DelegateCommand(ExecuteLoad));
// 带参数命令
private DelegateCommand<string> _deleteCommand;
public DelegateCommand<string> DeleteCommand =>
_deleteCommand ?? (_deleteCommand = new DelegateCommand<string>(
ExecuteDelete, CanExecuteDelete));
// 可观察属性,用于触发 CanExecute 重新评估
private bool _isLoading;
public bool IsLoading
{
get => _isLoading;
set => SetProperty(ref _isLoading, value);
}
private void ExecuteLoad()
{
IsLoading = true;
// 执行加载逻辑...
IsLoading = false;
}
private void ExecuteDelete(string parameter)
{
// 删除指定项
}
private bool CanExecuteDelete(string parameter)
{
return !string.IsNullOrEmpty(parameter) && !IsLoading;
}
// 观察命令:当指定属性变化时自动触发 CanExecuteChanged
public MainWindowViewModel()
{
DeleteCommand.ObservesProperty(() => IsLoading);
}
}
ObservesProperty 方法可以让命令自动监听属性变化,无需手动调用 RaiseCanExecuteChanged。
3.3 ViewModelLocator 自动绑定
Prism 的 ViewModelLocator 通过约定自动将 View 与 ViewModel 关联,默认规则是:
- Views 在
Views命名空间,ViewModels 在ViewModels命名空间 MainWindow→MainWindowViewModelEmployeeView→EmployeeViewModel
这意味着你不需要 手动设置 DataContext,只需遵循命名约定即可。
如需手动控制或禁用自动绑定,可以在 View 的 XAML 中设置:
xml
<Window x:Class="PrismDemo.Views.MyView"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="False">
<!-- 手动设置 DataContext -->
</Window>
四、区域与导航系统
4.1 区域(Region)概念
区域是 Prism 中用于动态管理视图的核心概念。你可以将应用程序的 UI 划分为多个区域,每个区域作为视图的容器,在运行时动态加载不同的内容。
定义区域:
xml
<Window x:Class="PrismDemo.Views.MainWindow"
xmlns:prism="http://prismlibrary.com/">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- 左侧导航区域 -->
<ContentControl Grid.Column="0"
prism:RegionManager.RegionName="NavigationRegion"/>
<!-- 主内容区域 -->
<ContentControl Grid.Column="1"
prism:RegionManager.RegionName="ContentRegion"/>
</Grid>
</Window>
常用的区域宿主控件:
ContentControl:显示单个视图ItemsControl:显示多个视图TabControl:以标签页形式显示视图
4.2 视图发现与视图注入
有两种方式将视图添加到区域中:
视图发现(View Discovery):在应用启动时自动将视图加载到区域
csharp
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// 自动将 NavigationView 加载到 NavigationRegion
containerRegistry.RegisterForNavigation<NavigationView>();
// 注册视图到指定区域(需要重写 ConfigureRegionAdapterMappings)
}
视图注入(View Injection):通过代码手动控制视图的创建和注入时机
csharp
public class MainWindowViewModel : BindableBase
{
private readonly IRegionManager _regionManager;
public MainWindowViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
}
private void LoadNavigationView()
{
var navigationView = Container.Resolve<NavigationView>();
IRegion region = _regionManager.Regions["NavigationRegion"];
region.Add(navigationView);
}
}
4.3 基于 URI 的导航
Prism 提供了更灵活的基于 URI 的导航机制,支持参数传递和导航回调:
注册导航视图:
csharp
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// 注册可导航的视图
containerRegistry.RegisterForNavigation<HomeView>("HomeView");
containerRegistry.RegisterForNavigation<EmployeeListView>("EmployeeList");
containerRegistry.RegisterForNavigation<EmployeeDetailView>("EmployeeDetail");
}
发起导航:
csharp
public class NavigationViewModel : BindableBase
{
private readonly IRegionManager _regionManager;
public DelegateCommand<string> NavigateCommand { get; }
public NavigationViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
NavigateCommand = new DelegateCommand<string>(ExecuteNavigate);
}
private void ExecuteNavigate(string viewName)
{
// 简单导航
_regionManager.RequestNavigate("ContentRegion", viewName);
// 带参数的导航
var parameters = new NavigationParameters
{
{ "id", 123 },
{ "mode", "edit" }
};
_regionManager.RequestNavigate("ContentRegion", viewName, parameters);
// 带回调的导航
_regionManager.RequestNavigate("ContentRegion", viewName,
result =>
{
if (result.Result == true)
StatusMessage = "导航成功";
else
StatusMessage = $"导航失败: {result.Error?.Message}";
});
}
}
4.4 INavigationAware 接口
让 ViewModel 实现 INavigationAware 接口,可以在导航过程中接收参数、确认导航或取消导航:
csharp
using Prism.Regions;
public class EmployeeDetailViewModel : BindableBase, INavigationAware
{
private int _employeeId;
// 导航到本页时调用
public void OnNavigatedTo(NavigationContext navigationContext)
{
// 获取导航参数
if (navigationContext.Parameters.ContainsKey("id"))
{
_employeeId = navigationContext.Parameters.GetValue<int>("id");
LoadEmployeeData(_employeeId);
}
}
// 是否可以导航到本页(可用于权限验证)
public bool IsNavigationTarget(NavigationContext navigationContext)
{
var id = navigationContext.Parameters.GetValue<int>("id");
return id > 0;
}
// 从本页离开时调用
public void OnNavigatedFrom(NavigationContext navigationContext)
{
// 清理资源,或保存草稿
}
}
4.5 导航日志
Prism 提供了导航日志功能,支持前进/后退操作:
csharp
public class EmployeeDetailViewModel : BindableBase, INavigationAware
{
private IRegionNavigationService _navigationService;
public DelegateCommand GoBackCommand { get; }
public DelegateCommand GoForwardCommand { get; }
public EmployeeDetailViewModel()
{
GoBackCommand = new DelegateCommand(GoBack, CanGoBack);
GoForwardCommand = new DelegateCommand(GoForward, CanGoForward);
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
_navigationService = navigationContext.NavigationService;
GoBackCommand.RaiseCanExecuteChanged();
}
private void GoBack()
{
if (_navigationService?.Journal.CanGoBack == true)
_navigationService.Journal.GoBack();
}
private bool CanGoBack() => _navigationService?.Journal.CanGoBack ?? false;
private void GoForward()
{
if (_navigationService?.Journal.CanGoForward == true)
_navigationService.Journal.GoForward();
}
private bool CanGoForward() => _navigationService?.Journal.CanGoForward ?? false;
}
五、对话框服务
5.1 传统弹窗的问题
在 MVVM 模式中,直接在 ViewModel 里调用 MessageBox.Show() 会破坏视图与逻辑的分离,使单元测试变得困难。Prism 提供了 IDialogService 来解决这个问题,让弹窗操作完全在 MVVM 模式下进行。
5.2 实现 IDialogAware 接口
首先创建对话框的 View 和 ViewModel,ViewModel 需要实现 IDialogAware 接口:
MyDialog.xaml(UserControl):
xml
<UserControl x:Class="PrismDemo.Views.MyDialog"
xmlns:prism="http://prismlibrary.com/">
<Grid Margin="20" MinWidth="300">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Title}" FontSize="16" FontWeight="Bold"/>
<TextBox Grid.Row="1" Text="{Binding InputText, UpdateSourceTrigger=PropertyChanged}"
Margin="0,15" Height="30"/>
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="确定" Command="{Binding ConfirmCommand}"
Width="80" Margin="5" Style="{StaticResource PrimaryButton}"/>
<Button Content="取消" Command="{Binding CancelCommand}"
Width="80" Margin="5"/>
</StackPanel>
</Grid>
</UserControl>
MyDialogViewModel.cs:
csharp
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using System;
namespace PrismDemo.ViewModels
{
public class MyDialogViewModel : BindableBase, IDialogAware
{
#region IDialogAware 实现
public string Title => "用户输入";
public event Action<IDialogResult> RequestClose;
public bool CanCloseDialog() => true;
public void OnDialogClosed()
{
// 对话框关闭时的清理逻辑
}
public void OnDialogOpened(IDialogParameters parameters)
{
// 接收传入的参数
if (parameters.ContainsKey("message"))
{
Message = parameters.GetValue<string>("message");
}
if (parameters.ContainsKey("defaultValue"))
{
InputText = parameters.GetValue<string>("defaultValue");
}
}
#endregion
#region 属性与命令
private string _message;
public string Message
{
get => _message;
set => SetProperty(ref _message, value);
}
private string _inputText;
public string InputText
{
get => _inputText;
set => SetProperty(ref _inputText, value);
}
public DelegateCommand ConfirmCommand { get; }
public DelegateCommand CancelCommand { get; }
#endregion
public MyDialogViewModel()
{
ConfirmCommand = new DelegateCommand(OnConfirm);
CancelCommand = new DelegateCommand(OnCancel);
}
private void OnConfirm()
{
var parameters = new DialogParameters
{
{ "result", InputText }
};
RequestClose?.Invoke(new DialogResult(ButtonResult.OK, parameters));
}
private void OnCancel()
{
RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel));
}
}
}
5.3 注册与使用对话框
注册对话框(在 App.xaml.cs 中):
csharp
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// 注册对话框
containerRegistry.RegisterDialog<MyDialog, MyDialogViewModel>();
// 可选:注册自定义对话框窗口样式
// containerRegistry.RegisterDialogWindow<CustomDialogWindow>();
}
调用对话框:
csharp
public class MainWindowViewModel : BindableBase
{
private readonly IDialogService _dialogService;
public DelegateCommand OpenDialogCommand { get; }
public MainWindowViewModel(IDialogService dialogService)
{
_dialogService = dialogService;
OpenDialogCommand = new DelegateCommand(OpenDialog);
}
private void OpenDialog()
{
var parameters = new DialogParameters
{
{ "message", "请输入您的姓名:" },
{ "defaultValue", "张三" }
};
_dialogService.ShowDialog("MyDialog", parameters, result =>
{
if (result.Result == ButtonResult.OK)
{
var userInput = result.Parameters.GetValue<string>("result");
StatusMessage = $"您输入了:{userInput}";
}
else
{
StatusMessage = "用户取消了操作";
}
});
}
}
5.4 自定义对话框窗口样式
如果不想使用 Prism 默认的对话框窗口,可以自定义窗口样式:
方式一:在 UserControl 中定义窗口样式
xml
<UserControl x:Class="PrismDemo.Views.MyDialog"
xmlns:prism="http://prismlibrary.com/">
<prism:Dialog.WindowStyle>
<Style TargetType="Window">
<Setter Property="Width" Value="450"/>
<Setter Property="Height" Value="300"/>
<Setter Property="ResizeMode" Value="NoResize"/>
<Setter Property="WindowStartupLocation" Value="CenterOwner"/>
<Setter Property="WindowStyle" Value="None"/>
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="Background" Value="Transparent"/>
</Style>
</prism:Dialog.WindowStyle>
<!-- 对话框内容 -->
</UserControl>
方式二:创建自定义窗口并注册
csharp
// CustomDialogWindow.xaml.cs
public partial class CustomDialogWindow : Window, IDialogWindow
{
public IDialogResult Result { get; set; }
public CustomDialogWindow()
{
InitializeComponent();
}
}
// App.xaml.cs
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialogWindow<CustomDialogWindow>();
}
六、完整示例:一个简单的员工管理系统
下面通过一个完整示例串联上述知识点,实现一个具备导航、弹窗、数据绑定功能的简易员工管理系统。
6.1 项目结构
EmployeeManager/
├── App.xaml / App.xaml.cs
├── Views/
│ ├── MainWindow.xaml
│ ├── EmployeeListView.xaml
│ ├── EmployeeDetailView.xaml
│ └── ConfirmDialog.xaml
├── ViewModels/
│ ├── MainWindowViewModel.cs
│ ├── EmployeeListViewModel.cs
│ ├── EmployeeDetailViewModel.cs
│ └── ConfirmDialogViewModel.cs
├── Models/
│ └── Employee.cs
└── Services/
├── IEmployeeService.cs
└── EmployeeService.cs
6.2 关键代码实现
MainWindow.xaml:
xml
<Window x:Class="EmployeeManager.Views.MainWindow"
xmlns:prism="http://prismlibrary.com/"
Title="{Binding Title}" Height="500" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 工具栏 -->
<StackPanel Orientation="Horizontal" Margin="10">
<Button Content="员工列表" Command="{Binding NavigateCommand}"
CommandParameter="EmployeeListView" Margin="5"/>
<Button Content="新增员工" Command="{Binding AddEmployeeCommand}" Margin="5"/>
</StackPanel>
<!-- 主内容区域 -->
<ContentControl Grid.Row="1"
prism:RegionManager.RegionName="ContentRegion"/>
</Grid>
</Window>
App.xaml.cs 注册配置:
csharp
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// 注册服务
containerRegistry.RegisterSingleton<IEmployeeService, EmployeeService>();
// 注册导航视图
containerRegistry.RegisterForNavigation<EmployeeListView>();
containerRegistry.RegisterForNavigation<EmployeeDetailView>();
// 注册对话框
containerRegistry.RegisterDialog<ConfirmDialog, ConfirmDialogViewModel>();
}
七、最佳实践与注意事项
7.1 服务生命周期管理
Prism 提供了多种服务注册方式,应根据场景选择合适的生命周期:
csharp
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// 瞬时:每次解析都创建新实例
containerRegistry.Register<IService, ServiceImplementation>();
// 单例:全局唯一实例
containerRegistry.RegisterSingleton<IConfigService, ConfigService>();
// 实例注册:注册已创建的实例
var logger = new LogService();
containerRegistry.RegisterInstance<ILogService>(logger);
}
7.2 模块化开发建议
对于大型项目,建议采用模块化架构:
- 每个业务模块独立为一个类库项目
- 模块实现
IModule接口,在OnInitialized中注册模块内的视图和服务 - 通过
ModuleCatalog配置模块加载方式(代码、目录扫描、配置文件)
7.3 注意事项
- 命名约定:严格遵循 Views/ViewModels 的命名约定,可避免手动配置 ViewModelLocator
- 内存管理 :实现
IDisposable并在OnNavigatedFrom中清理事件订阅 - UI 线程 :属性变更会自动跨线程处理,但耗时操作仍需使用
Task.Run - 对话框结果 :不要在
OnDialogClosed中调用RequestClose,此时事件已为 null
八、总结
Prism 为 WPF 开发提供了完整的 MVVM 基础设施,其核心优势在于:
- 关注点分离:通过 ViewModelLocator、数据绑定和命令,彻底分离视图与逻辑
- 松耦合通信:EventAggregator 和 DialogService 实现组件间的低耦合交互
- 灵活的导航:基于区域的导航系统支持复杂的页面流转和参数传递
- 可测试性:依赖注入和接口抽象使单元测试变得简单
本文覆盖了 Prism 的核心功能,包括环境搭建、MVVM 基础、区域导航和对话框服务。掌握这些内容后,你已经能够使用 Prism 开发结构清晰、易于维护的 WPF 企业级应用。
建议进一步阅读 Prism 官方文档 和 GitHub 示例项目,深入了解事件聚合器、模块化等高级特性。