You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 18:53:12