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

Blazor Scoped服务调用Dispose后再次进入页面未触发构造函数问题

问题原因

Blazor 中注册为Scoped的服务默认生命周期作用域为整个用户会话:Blazor WASM 场景下对应浏览器单个标签页的完整生命周期,Blazor Server 场景下对应单个 SignalR 连接的生命周期,不会随页面导航切换自动销毁重建。

你手动调用Dispose方法仅会执行该服务实例的自定义释放逻辑,并不会将该实例从 DI 容器的 Scoped 作用域缓存中移除。后续再次请求注入ProfileService时,DI 容器仍会返回之前创建的旧实例,自然不会触发构造函数执行。

解决方案

如果需要实现ProfileService跟随ProfileView页面的加载/卸载完成实例的创建/销毁,可以通过以下两种方案实现:

方案1:继承OwningComponentBase<T>基类

Blazor 原生提供了OwningComponentBase<T>组件基类,会自动为当前组件创建独立的 DI 作用域,组件销毁时自动销毁该作用域及作用域内所有服务:

  1. 修改ProfileView的父类为OwningComponentBase<ProfileService>,替换原有的ComponentBase
  2. 不要使用@inject直接注入ProfileService,通过基类提供的Service属性获取服务实例即可
  3. 页面导航离开触发组件销毁时,独立作用域会自动释放,下次进入页面会创建新的作用域及ProfileService实例。

方案2:手动管理DI作用域

如果不想修改组件基类,也可以手动控制作用域的创建和销毁:

  1. 首先给ProfileView注入IServiceScopeFactory
  2. 在页面初始化时创建独立作用域并获取服务实例:
private IServiceScope _serviceScope;
private ProfileService _profileService;

protected override async Task OnInitializedAsync()
{
    _serviceScope = _serviceScopeFactory.CreateScope();
    _profileService = _serviceScope.ServiceProvider.GetRequiredService<ProfileService>();
    // 后续业务逻辑均使用此处获取的_profileService
}
  1. 在组件的释放方法中销毁作用域:
public async ValueTask DisposeAsync()
{
    if (_serviceScope != null)
    {
        await _serviceScope.DisposeAsync();
    }
}

注意:不要手动调用 DI 容器托管的服务的Dispose方法,对应作用域销毁时容器会自动执行所有服务的释放逻辑,手动调用仅会执行清理逻辑不会更新容器的实例缓存,反而可能导致不可预期的问题。

内容的提问来源于stack exchange,提问作者Lapish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 22:06:03