目录
2. DelegateCommand/DelegateCommand :行为的封装
3. 消息委托的引用方式(keepSubscriberReferenceAlive)
Prism框架中的区域化管理(Region Management)
Prism中的基本对象
数据与行为对象
1. BindableBase:数据绑定的基础
BindableBase
是 Prism 中实现 数据绑定通知 的核心基类,继承自 INotifyPropertyChanged
接口。它简化了属性变更通知的触发逻辑,确保 UI 能够自动响应数据变化。
作用与特性
- 自动触发通知:通过
SetProperty
方法设置属性值,自动触发PropertyChanged
事件。 - 减少样板代码:避免手动编写
if (value != field) { ... }
和事件触发逻辑。 - 支持派生类:ViewModel 通常继承
BindableBase
,直接使用其功能。
关键方法
SetProperty(ref T field, T value)
:基础属性设置。SetProperty(ref T field, T value, Action onChanged)
:设置属性并执行回调。RaisePropertyChanged(string propertyName)
:手动触发指定属性的通知。
使用示例
public class UserViewModel : BindableBase
{
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value); // 自动触发PropertyChanged事件
}
private int _age;
public int Age
{
get => _age;
set => SetProperty(ref _age, value, () =>
{
// 可选:属性变更后的回调逻辑(如验证)
});
}
}
2. DelegateCommand/DelegateCommand<T>:行为的封装
DelegateCommand
是 Prism 对 ICommand
接口的实现,用于将 UI 操作(如按钮点击) 绑定到 ViewModel 中的方法,支持条件执行(CanExecute
)。
作用与特性
- 解耦 UI 与逻辑:将点击事件转化为命令,直接在 ViewModel 中处理。
- 支持条件执行:通过
CanExecute
控制命令是否可用(如按钮禁用状态)。 - 泛型与非泛型:
DelegateCommand
无参数,DelegateCommand<T>
支持参数传递。
关键方法
Execute()
:命令执行时调用的方法。CanExecute()
:返回bool
,决定命令是否可用。RaiseCanExecuteChanged()
:手动触发CanExecute
的重新检查。
使用示例
无参数命令
public class UserViewModel : BindableBase
{
// 定义命令
public DelegateCommand SaveCommand { get; }
public UserViewModel()
{
// 绑定执行方法与条件检查
SaveCommand = new DelegateCommand(ExecuteSave, CanSave);
}
private void ExecuteSave()
{
// 保存逻辑
}
private bool CanSave()
{
// 检查保存条件(如数据有效性)
return !string.IsNullOrEmpty(Name);
}
// 当Name属性变化时,手动触发CanExecute检查
public string Name
{
get => _name;
set
{
SetProperty(ref _name, value);
SaveCommand.RaiseCanExecuteChanged(); // 通知命令重新检查条件
}
}
}
带参数的命令
public DelegateCommand<int> DeleteCommand { get; }
public UserViewModel()
{
DeleteCommand = new DelegateCommand<int>(ExecuteDelete, CanDelete);
}
private void ExecuteDelete(int userId)
{
// 删除指定用户
}
private bool CanDelete(int userId)
{
return userId > 0; // 仅当userId有效时允许执行
}
在 XAML 中绑定命令
<Button Command="{Binding SaveCommand}" Content="Save" />
<Button Command="{Binding DeleteCommand}" CommandParameter="{Binding SelectedUser.Id}" Content="Delete" />
Prism框架中的IoC(控制反转)容器
在Prism框架中,IoC容器是实现依赖注入(DI)的核心机制,用于管理组件生命周期、解耦服务依赖并支持模块化开发。Prism默认支持多种容器(如 Unity、DryIoc)。
1. 核心接口与配置
1.1 容器配置入口
Prism应用的入口类(继承自PrismApplication
)负责初始化容器:
public partial class App : PrismApplication
{
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// 注册全局服务
containerRegistry.RegisterSingleton<ILogger, FileLogger>();
containerRegistry.Register<IDataService, DatabaseService>();
}
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
}
1.2 关键接口
IContainerRegistry
:用于注册服务(接口与实现的映射)。IContainerProvider
:用于解析(获取)已注册的服务实例。
2. 服务注册方式
2.1 基础注册
接口绑定实现类:
containerRegistry.Register<IMessageService, EmailService>();
直接注册具体类(无需接口):
containerRegistry.Register<DataProcessor>();
2.2 生命周期控制
单例(Singleton):全局唯一实例。
containerRegistry.RegisterSingleton<IConfigService, AppConfigService>();
瞬态(Transient):每次解析创建新实例。
containerRegistry.Register<ITransientService, TransientService>();
实例注册:直接注入已有实例。
var logger = new FileLogger();
containerRegistry.RegisterInstance<ILogger>(logger);
3. 依赖注入方式
3.1 构造函数注入(推荐)
ViewModel或服务通过构造函数声明依赖,容器自动注入:
public class UserViewModel
{
private readonly IDataService _dataService;
public UserViewModel(IDataService dataService)
{
_dataService = dataService; // 由容器自动注入
}
}
3.2 属性注入(需谨慎)
通过 [Dependency]
特性标记需注入的属性:
public class OrderService
{
[Dependency]
public ILogger Logger { get; set; }
}
4. 模块化中的IoC
每个Prism模块(实现 IModule
接口)可独立注册服务:
public class DataModule : IModule
{
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register<IDatabaseRepository, SqlRepository>();
}
public void OnInitialized(IContainerProvider containerProvider)
{
// 模块初始化逻辑(如预加载数据)
}
}
5. 解析服务
通过 IContainerProvider
或构造函数隐式解析服务:
// 在ViewModel中解析服务
public class MainViewModel
{
public MainViewModel(IContainerProvider containerProvider)
{
var service = containerProvider.Resolve<IDataService>();
}
}
6. 高级功能
6.1 命名注册
同一接口多个实现时,使用名称区分:
containerRegistry.Register<IMessageService, EmailService>("Email");
containerRegistry.Register<IMessageService, SmsService>("SMS");
// 解析指定名称的实现
var emailService = container.Resolve<IMessageService>("Email");
6.2 延迟加载与工厂模式
通过 Func<T>
或 IocContainer.CreateScope
实现复杂依赖管理:
containerRegistry.Register<IServiceFactory>(() => new ServiceFactory());
Prism框架中的消息对象(事件总线)
在Prism框架中,事件总线(Event Aggregator) 是实现松耦合跨组件通信的核心机制。它通过发布-订阅模式(Pub-Sub)让不同模块、视图或服务之间无需直接引用即可传递消息,尤其适用于模块化架构和MVVM模式。
1. 核心组件
IEventAggregator
:
事件聚合器的入口接口,负责创建和管理事件对象。
通过依赖注入获取实例:
public class MyViewModel
{
private readonly IEventAggregator _eventAggregator;
public MyViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
}
PubSubEvent<T>
:
所有自定义事件的基类,泛型T
定义事件传递的数据类型。
开发者需继承此类创建特定事件:
public class UserLoggedInEvent : PubSubEvent<UserInfo> { }
2. 使用流程
2.1 定义事件类
创建继承自 PubSubEvent<T>
的事件类,定义事件的数据类型:
// 无参数事件
public class AppShutdownEvent : PubSubEvent { }
// 带参数事件
public class OrderSubmittedEvent : PubSubEvent<Order> { }
2.2 发布事件
通过 GetEvent<TEvent>()
获取事件实例并发布数据:
// 发布无参数事件
_eventAggregator.GetEvent<AppShutdownEvent>().Publish();
// 发布带参数事件
var order = new Order { Id = 123, Amount = 100.0 };
_eventAggregator.GetEvent<OrderSubmittedEvent>().Publish(order);
2.3 订阅事件
// 订阅事件(自动强引用,需手动取消订阅)
_eventAggregator.GetEvent<OrderSubmittedEvent>()
.Subscribe(OnOrderSubmitted);
// 处理事件的回调方法
private void OnOrderSubmitted(Order order)
{
// 处理订单提交逻辑
MessageBox.Show($"订单 {order.Id} 已提交!");
}
3. 高级配置
3.1 订阅选项
通过 Subscribe
方法的参数配置订阅行为:
_eventAggregator.GetEvent<OrderSubmittedEvent>()
.Subscribe(
onOrderSubmitted, // 回调方法
ThreadOption.UIThread, // 在UI线程执行
keepSubscriberReferenceAlive: false, // 弱引用
filter: order => order.UserId == _currentUserId // 仅处理当前用户的订单
);
各参数的应用场景总结
参数 | 典型场景 |
回调方法 | 执行具体的业务逻辑(如更新数据库、刷新UI)。 |
| 过滤无关事件(如只处理特定用户或状态的数据)。 |
| 控制订阅者生命周期(View/ViewModel用弱引用,服务层可强引用)。 |
| 解决跨线程问题(UI操作必须在UI线程,耗时操作在后台线程)。 |
详细使用教程
1. 主要委托方法(回调逻辑)
- 作用:定义事件触发时执行的核心逻辑。
- 语法:通过
Action<T>
或带参数的委托实现。 - 示例:
_eventAggregator.GetEvent<OrderSubmittedEvent>()
.Subscribe(OnOrderSubmitted); // OnOrderSubmitted为回调方法
private void OnOrderSubmitted(Order order)
{
// 处理订单提交逻辑
_logger.Log($"订单 {order.Id} 已处理");
}
2. 消息过滤条件(filter
)
- 作用:根据条件过滤事件,仅当数据满足条件时触发回调。
- 类型:
Predicate<T>
(返回bool
的表达式)。 - 示例:
.Subscribe(OnHighValueOrder,
filter: order => order.Amount > 1000 // 仅处理金额超过1000的订单
);
- 场景:
-
- 仅处理特定类型的数据(如高优先级任务)。
- 避免不必要的事件响应(如仅关注当前用户的订单)。
3. 消息委托的引用方式(keepSubscriberReferenceAlive
)
- 作用:控制订阅者的生命周期引用方式,防止内存泄漏。
- 可选值:
-
true
:强引用,订阅者不会被垃圾回收,需手动取消订阅。false
(默认):弱引用,订阅者销毁后自动取消订阅。
- 示例:
// 使用弱引用(推荐)
.Subscribe(OnOrderSubmitted,
keepSubscriberReferenceAlive: false
);
// 使用强引用(需手动管理)
.Subscribe(OnOrderSubmitted,
keepSubscriberReferenceAlive: true
);
- 最佳实践:
-
- ViewModel/View 订阅事件时,默认使用弱引用(避免因未取消订阅导致内存泄漏)。
- 全局服务 或长期存在的对象可使用强引用,但需在不再需要时调用
Unsubscribe
。
4. 多线程状态控制(ThreadOption
)
- 作用:指定回调方法在哪个线程执行,解决跨线程访问UI的问题。
- 可选值:
-
PublisherThread
:在发布事件的线程执行(默认)。UIThread
:在UI线程执行(安全更新界面)。BackgroundThread
:在线程池后台线程执行(避免阻塞UI)。
- 示例:
// 在UI线程更新界面
.Subscribe(UpdateUI,
ThreadOption.UIThread
);
// 在后台线程处理耗时操作
.Subscribe(ProcessData,
ThreadOption.BackgroundThread
);
- 线程安全场景:
-
- UI操作:必须使用
UIThread
,否则会抛出跨线程异常。 - 数据计算/IO操作:使用
BackgroundThread
避免阻塞主线程。 - 同步上下文:若发布者本身在UI线程,
PublisherThread
等同于UIThread
。
- UI操作:必须使用
3.2 取消订阅
- 手动取消:
保存订阅令牌(SubscriptionToken
),调用Unsubscribe
方法。
private SubscriptionToken _token;
_token = _eventAggregator.GetEvent<OrderSubmittedEvent>()
.Subscribe(OnOrderSubmitted);
// 取消订阅
_eventAggregator.GetEvent<OrderSubmittedEvent>().Unsubscribe(_token);
- 自动取消:
使用弱引用(keepSubscriberReferenceAlive: false
),订阅者销毁时自动取消订阅。
4. 实际应用场景
4.1 跨模块通信
- 场景:订单模块提交订单后,通知购物车模块清空购物车。
- 实现:
// 订单模块发布事件
_eventAggregator.GetEvent<OrderSubmittedEvent>().Publish(order);
// 购物车模块订阅事件
_eventAggregator.GetEvent<OrderSubmittedEvent>()
.Subscribe(_ => ClearCart());
4.2 全局状态通知
- 场景:用户登录后,通知所有模块更新界面。
- 实现:
// 登录成功后发布事件
_eventAggregator.GetEvent<UserLoggedInEvent>().Publish(userInfo);
// 各模块订阅事件
_eventAggregator.GetEvent<UserLoggedInEvent>()
.Subscribe(UpdateUI);
4.3 弹窗交互
- 场景:在ViewModel中触发弹窗,无需直接操作View。
- 实现:
// 定义弹窗事件
public class ShowDialogEvent : PubSubEvent<DialogParameters> { }
// 发布弹窗请求
var parameters = new DialogParameters { { "message", "保存成功!" } };
_eventAggregator.GetEvent<ShowDialogEvent>().Publish(parameters);
// 弹窗服务订阅事件并显示弹窗
_eventAggregator.GetEvent<ShowDialogEvent>()
.Subscribe(ShowDialog, ThreadOption.UIThread);
private void ShowDialog(DialogParameters parameters)
{
_dialogService.ShowDialog("MessageDialog", parameters);
}
Prism框架中的弹窗对象
1. 核心组件
1.1 IDialogService
- 作用:管理弹窗的显示、关闭及结果回调。
- 关键方法:
// 显示弹窗
void ShowDialog(string name, IDialogParameters parameters, Action<IDialogResult> callback);
// 显示模态弹窗(阻塞式)
void Show(string name, IDialogParameters parameters, Action<IDialogResult> callback);
1.2 IDialogAware
- 作用:弹窗ViewModel必须实现的接口,定义弹窗的生命周期方法。
- 核心成员:
bool CanCloseDialog(); // 控制弹窗是否允许关闭
void OnDialogOpened(IDialogParameters parameters); // 弹窗打开时接收参数
string Title { get; } // 弹窗标题
2. 创建弹窗的完整流程
2.1 定义弹窗视图(View)
- XAML示例(
WarningDialog.xaml
):
<UserControl
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<StackPanel>
<TextBlock Text="{Binding Message}" Margin="10"/>
<Button Content="确认" Command="{Binding ConfirmCommand}" />
<Button Content="取消" Command="{Binding CancelCommand}" />
</StackPanel>
</UserControl>
2.2 实现弹窗ViewModel
- 继承
IDialogAware
并处理逻辑:
public class WarningDialogViewModel : BindableBase, IDialogAware
{
// 实现IDialogAware
public string Title => "警告";// 弹出窗口的标题
public event Action<IDialogResult> RequestClose;// 执行关闭返回
private string _message;
public string Message
{
get => _message;
set => SetProperty(ref _message, value);
}
// 命令定义
public DelegateCommand ConfirmCommand { get; }
public DelegateCommand CancelCommand { get; }
public WarningDialogViewModel()
{
ConfirmCommand = new DelegateCommand(() =>RequestClose?.Invoke(new DialogResult(ButtonResult.OK)));
CancelCommand = new DelegateCommand(() =>RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel)));
}
// 当弹出窗口关闭时执行的逻辑
public void OnDialogClosed()
{
}
// 当弹出窗口打开的时候执行的逻辑
public void OnDialogOpened(IDialogParameters parameters)
{
// 接收参数
Message = parameters.GetValue<string>("message");
}
public bool CanCloseDialog() => true; // 允许直接关闭
}
2.3 注册弹窗
- 在App或模块中注册:
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog<WarningDialog, WarningDialogViewModel>("WarningDialog");
}
3. 触发弹窗显示
3.1 在ViewModel中调用弹窗
public class MainViewModel
{
private readonly IDialogService _dialogService;
public MainViewModel(IDialogService dialogService)
{
_dialogService = dialogService;
}
public DelegateCommand ShowDialogCommand => new DelegateCommand(() =>
{
var parameters = new DialogParameters
{
{ "message", "确定要删除此文件吗?" }
};
_dialogService.ShowDialog("WarningDialog", parameters, result =>
{
if (result.Result == ButtonResult.OK)
{
// 用户点击确认后的逻辑
DeleteFile();
}
});
});
}
3.2 直接通过View触发(不推荐,破坏MVVM)
<Button Command="{Binding ShowDialogCommand}" Content="显示弹窗" />
4. 高级功能
4.1 自定义弹窗样式
- 覆盖默认样式:
在App.xaml
中定义全局弹窗样式:
<Style TargetType="prism:Dialog" BasedOn="{StaticResource PrismDialogStyle}">
<Setter Property="Width" Value="400"/>
<Setter Property="Height" Value="250"/>
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterScreen"/>
</Style>
4.2 异步弹窗交互
- 使用
Task
封装弹窗结果:
public async Task<bool> ShowConfirmationAsync(string message)
{
var tcs = new TaskCompletionSource<bool>();
var parameters = new DialogParameters { { "message", message } };
_dialogService.ShowDialog("ConfirmationDialog", parameters, result =>
{
tcs.SetResult(result.Result == ButtonResult.OK);
});
return await tcs.Task;
}
4.3 弹窗传参与复杂数据
- 传递对象参数:
var order = new Order { Id = 123, Amount = 100.0 };
parameters.Add("order", order);
- 接收并处理对象:
public void OnDialogOpened(IDialogParameters parameters)
{
var order = parameters.GetValue<Order>("order");
// 使用order数据...
}
Prism框架中的区域化管理(Region Management)
Prism的 区域化管理(Region Management) 是其核心功能之一,用于实现动态UI组合和模块化布局。通过将界面划分为逻辑区域(Regions),各模块可独立向这些区域注入视图,无需直接操作主窗口控件,从而实现高度解耦和灵活扩展。
1. 核心概念
- 区域(Region):UI中的占位符容器(如
ContentControl
、TabControl
),用于动态承载视图。 - 区域管理器(
IRegionManager
):负责管理区域的生命周期、视图注入和导航。 - 区域适配器(
RegionAdapter
):将不同控件(如ItemsControl
、TabControl
)适配为可管理的区域。
2. 区域的定义与注册
2.1 在XAML中标记区域
使用 prism:RegionManager.RegionName
附加属性定义区域:
<!-- Shell.xaml -->
<Window>
<Grid>
<!-- 顶部导航栏区域 -->
<ContentControl prism:RegionManager.RegionName="HeaderRegion" />
<!-- 主内容区域 -->
<ContentControl prism:RegionManager.RegionName="MainRegion" />
<!-- 侧边栏区域 -->
<ItemsControl prism:RegionManager.RegionName="SidebarRegion" />
</Grid>
</Window>
2.2 通过代码动态注册区域
在ViewModel或模块中动态创建区域:
var regionManager = Container.Resolve<IRegionManager>();
regionManager.Regions.Add("DynamicRegion", new Region());
3. 视图注入与导航
3.1 向区域注入视图
- 方法1:直接注册视图
在模块初始化时注册视图到指定区域:
public class OrdersModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("MainRegion", typeof(OrderListView));
}
}
- 方法2:通过导航请求加载视图
动态导航到指定视图(支持参数传递):
var parameters = new NavigationParameters();
parameters.Add("orderId", 123);
_regionManager.RequestNavigate("MainRegion", "OrderDetailView", parameters);
3.2 视图导航生命周期
在ViewModel中实现 INavigationAware
接口处理导航事件:
public class OrderDetailViewModel : INavigationAware
{
public void OnNavigatedTo(NavigationContext navigationContext)
{
// 获取参数
var orderId = navigationContext.Parameters.GetValue<int>("orderId");
LoadOrder(orderId);
}
public bool IsNavigationTarget(NavigationContext navigationContext) => true;
public void OnNavigatedFrom(NavigationContext navigationContext)
{
// 清理资源
}
}
4. 区域适配器(支持复杂控件)
Prism内置了多种区域适配器,扩展支持常见控件:
ContentControlRegionAdapter
:适配ContentControl
(单视图替换)。ItemsControlRegionAdapter
:适配ItemsControl
(多视图叠加)。SelectorRegionAdapter
:适配TabControl
、ListBox
等(支持选中项切换)。
自定义区域适配器
若需支持特殊控件(如第三方图表容器),可继承 RegionAdapterBase<T>
:
public class ChartRegionAdapter : RegionAdapterBase<ChartControl>
{
protected override void Adapt(IRegion region, ChartControl regionTarget)
{
region.Views.CollectionChanged += (sender, args) =>
{
foreach (var view in region.Views)
{
regionTarget.AddSeries(view as ChartSeries);
}
};
}
}
// 注册适配器
protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
{
var mappings = base.ConfigureRegionAdapterMappings();
mappings.RegisterMapping(typeof(ChartControl), Container.Resolve<ChartRegionAdapter>());
return mappings;
}
5. 区域上下文(共享数据)
- 设置区域上下文:
向区域传递共享数据,供子视图访问:
_regionManager.Regions["MainRegion"].Context = new SharedData { UserId = 456 };
- 在视图中获取上下文:
通过IRegionMemberLifetime
或依赖注入获取:
public class OrderListView
{
public OrderListView(IRegionManager regionManager)
{
var context = regionManager.Regions["MainRegion"].Context;
}
}
Prism框架中的模块化设计
1. 模块的核心组成
每个模块需实现 IModule
接口,包含两个关键方法:
public interface IModule
{
void RegisterTypes(IContainerRegistry containerRegistry); // 注册依赖
void OnInitialized(IContainerProvider containerProvider); // 模块初始化逻辑
}
2. 模块的创建与配置
2.1 定义模块
public class OrdersModule : IModule
{
// 注册模块专属服务
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register<IOrderService, OrderService>();
containerRegistry.RegisterForNavigation<OrderListView>("OrderList"); // 注册视图
}
// 初始化模块(如预加载数据、订阅全局事件)
public void OnInitialized(IContainerProvider containerProvider)
{
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("MainRegion", typeof(OrderListView));
}
}
2.2 模块目录配置
通过 ModuleCatalog
定义模块的加载顺序和依赖关系,支持多种配置方式:
- 代码配置(显式声明):
protected override void ConfigureModuleCatalog(IModuleCatalog catalog)
{
catalog.AddModule<OrdersModule>()
.AddModule<CustomersModule>(dependsOn: nameof(OrdersModule)) // 依赖OrdersModule
.AddModule<ReportsModule>(InitializationMode.OnDemand); // 按需加载
}
- 文件配置(XML/JSON):
<!-- modules.xml -->
<Modules>
<Module Name="OrdersModule" Type="MyApp.Orders.OrdersModule, MyApp.Orders" />
<Module Name="CustomersModule" Type="MyApp.Customers.CustomersModule" StartupLoaded="false" />
</Modules>
protected override IModuleCatalog CreateModuleCatalog()
{
return new ConfigurationModuleCatalog(new Uri("pack://application:,,,/modules.xml"));
}
- 目录扫描(动态发现):
protected override IModuleCatalog CreateModuleCatalog()
{
return new DirectoryModuleCatalog { ModulePath = @".\Modules" };
}
3. 模块加载策略
- 按需加载(On-Demand):
延迟加载模块以减少启动时间,通过代码触发加载:
var moduleManager = containerProvider.Resolve<IModuleManager>();
moduleManager.LoadModule("ReportsModule");
- 按顺序加载:
通过dependsOn
确保依赖模块优先初始化。 - 条件加载:
根据运行时环境(如用户权限)动态决定是否加载模块:
if (user.IsAdmin)
moduleManager.LoadModule("AdminToolsModule");
4. 模块间的通信与解耦
- 依赖注入:
模块通过接口共享服务,避免直接依赖实现类。
// 模块A注册服务
public void RegisterTypes(IContainerRegistry registry)
{
registry.Register<IDataExporter, CsvExporter>();
}
// 模块B使用服务
public class ReportViewModel
{
public ReportViewModel(IDataExporter exporter) { ... }
}
- 事件聚合器:
跨模块事件通知,实现松耦合交互。
// 模块A发布事件
_eventAggregator.GetEvent<DataUpdatedEvent>().Publish(data);
// 模块B订阅事件
_eventAggregator.GetEvent<DataUpdatedEvent>().Subscribe(RefreshData);