Avalonia项目使用MediatR Publish时单例MainViewModel重复创建问题
解决方案
问题根源在于:MediatR默认扫描程序集时,会自动将实现INotificationHandler的MainViewModel注册为**瞬态(Transient)**服务,这会覆盖你之前注册的单例配置——当MediatR需要处理通知时,会创建新的MainViewModel实例,而非使用已有的单例。
要让MediatR复用已注册的单例MainViewModel,需要做两处修改:
1. 调整MediatR的自动扫描规则,排除MainViewModel
修改AddMediatR的配置,扫描程序集时跳过MainViewModel,避免MediatR自动注册它为瞬态处理程序:
services.AddMediatR(cfg => { // 扫描当前程序集,但排除MainViewModel,防止自动注册为Transient cfg.RegisterServicesFromAssembly(typeof(App).Assembly, type => type != typeof(MainViewModel)); });
2. 手动注册MainViewModel为通知处理程序(单例)
在注册完ViewModel之后,手动将MainViewModel绑定到INotificationHandler<ChangeViewModelEvent>,指定使用已有的单例实例:
// 在RegisterViewsAndViewModels调用之后、AddMediatR调用之后添加 services.AddSingleton<INotificationHandler<ChangeViewModelEvent>>(sp => sp.GetRequiredService<MainViewModel>() );
完整的ConfigureServices代码修改后如下:
.ConfigureServices((_, services) => { services.UseMicrosoftDependencyResolver(); RegisterViewsAndViewModels(services); var resolver = Locator.CurrentMutable; resolver.InitializeSplat(); resolver.InitializeReactiveUI(); services.AddMediatR(cfg => { cfg.RegisterServicesFromAssembly(typeof(App).Assembly, type => type != typeof(MainViewModel)); }); // 手动绑定处理程序到单例MainViewModel services.AddSingleton<INotificationHandler<ChangeViewModelEvent>>(sp => sp.GetRequiredService<MainViewModel>() ); })
原理说明
- 第一步阻止MediatR自动注册
MainViewModel为瞬态处理程序,避免和你之前的单例注册冲突。 - 第二步明确告诉DI容器:当需要
INotificationHandler<ChangeViewModelEvent>时,直接从容器中获取已注册的MainViewModel单例,而非创建新实例。
这样修改后,MediatR发布通知时,会复用你在RegisterViewsAndViewModels中注册的MainViewModel单例,不会再创建新实例。
内容的提问来源于stack exchange,提问作者LuckyGeorge1975
相关产品推荐
相关产品推荐

