Blazor Server中继承RevalidatingServerAuthenticationStateProvider的类无法注入Fluxor IDispatcher
问题根因
RevalidatingServerAuthenticationStateProvider 在Blazor Server中默认以单例生命周期注册,而Fluxor的IDispatcher默认是Scoped生命周期,单例服务无法直接注入Scoped服务,这就是构造函数注入导致空白页、属性注入返回null的核心原因。
可行解决方案
方案1:手动创建Scoped作用域获取IDispatcher(最推荐)
在自定义的认证状态提供类中注入根IServiceProvider,在需要分发消息的方法内手动创建Scoped作用域,再从作用域中获取IDispatcher实例使用,示例代码如下:
public class CustomAuthStateProvider : RevalidatingServerAuthenticationStateProvider { private readonly IServiceProvider _rootServiceProvider; public CustomAuthStateProvider(ILoggerFactory loggerFactory, IServiceProvider rootServiceProvider) : base(loggerFactory) { _rootServiceProvider = rootServiceProvider; } protected override async Task<bool> ValidateAuthenticationStateAsync(AuthenticationState authenticationState, CancellationToken cancellationToken) { // 原有令牌刷新逻辑,获取新的访问令牌 var newAccessToken = await RefreshAccessTokenAsync(authenticationState); // 创建临时Scoped作用域获取IDispatcher using var scoped = _rootServiceProvider.CreateScope(); var dispatcher = scoped.ServiceProvider.GetRequiredService<IDispatcher>(); // 分发令牌刷新事件 dispatcher.Dispatch(new AccessTokenRefreshedEvent(newAccessToken)); // 剩余的认证状态校验逻辑 return !string.IsNullOrEmpty(newAccessToken); } // 其他你需要重写的逻辑,例如重写RevalidationInterval指定刷新间隔 protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(30); }
方案2:调整服务注册生命周期(不推荐)
你可以在注册Fluxor服务时手动指定IDispatcher的生命周期为单例,但该方案存在严重风险:Fluxor默认将IDispatcher注册为Scoped是为了和Blazor Server的单用户Circuit会话绑定,避免不同用户的消息互相干扰,改为单例后会出现跨用户的状态异常,仅可在你确认所有分发的消息都是全局无用户差异的场景下使用。
注意事项
- 不要缓存从临时Scoped作用域中获取的
IDispatcher实例,用完即释放作用域,避免出现服务泄漏和跨请求状态污染 - 如果需要携带当前用户身份信息到分发的事件中,直接从
ValidateAuthenticationStateAsync方法入参的authenticationState对象中获取即可,不需要额外注入用户相关服务
内容的提问来源于stack exchange,提问作者sianabanana
相关产品推荐
相关产品推荐

