Blazor Server中如何实现每次按钮点击获取新DI实例?
解决Blazor Server中点击按钮时无法获取Transient服务新实例的问题
问题根源
Blazor Server的组件默认是Scoped生命周期,哪怕你把ILoginService注册为Transient,组件在初始化阶段注入的服务实例会被组件一直持有。后续的按钮点击事件复用的都是这个已存在的实例,不会自动创建新的。
解决方案1:通过IServiceProvider手动创建实例
在组件中注入IServiceProvider,每次点击按钮时,从服务提供者中手动获取新的ILoginService实例:
@inject IServiceProvider ServiceProvider <button @onclick="HandleLogin">重试登录</button> @code { private async Task HandleLogin() { // 每次点击都创建新的ILoginService实例 var loginService = ServiceProvider.GetRequiredService<ILoginService>(); // 这里使用loginService执行登录逻辑,每次都是新实例 var result = await loginService.AttemptLogin(); // 处理结果... } }
解决方案2:使用工厂模式封装实例创建
定义一个工厂接口来负责创建ILoginService的新实例,将工厂注册到DI容器,组件注入工厂后调用创建方法:
- 定义工厂接口:
public interface ILoginServiceFactory { ILoginService Create(); }
- 实现工厂类:
public class LoginServiceFactory : ILoginServiceFactory { private readonly IServiceProvider _serviceProvider; public LoginServiceFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public ILoginService Create() { // 每次调用Create都返回新实例 return _serviceProvider.GetRequiredService<ILoginService>(); } }
- 在Program.cs中注册服务和工厂:
builder.Services.AddTransient<ILoginService, LoginService>(); builder.Services.AddTransient<ILoginServiceFactory, LoginServiceFactory>();
- 在组件中使用工厂:
@inject ILoginServiceFactory LoginServiceFactory <button @onclick="HandleLogin">重试登录</button> @code { private async Task HandleLogin() { var loginService = LoginServiceFactory.Create(); var result = await loginService.AttemptLogin(); // 处理结果... } }
关键说明
- 不要在组件的构造函数或属性注入中直接获取
ILoginService,因为这只会在组件初始化时执行一次,后续点击无法更新实例。 - 上述两种方法都能确保每次按钮点击时拿到全新的
ILoginService实例,满足你重试时ID更新的需求。
内容的提问来源于stack exchange,提问作者Edison C
相关产品推荐
相关产品推荐

