Blazor注入ApplicationState服务提示无对应已注册服务类型报错
报错原因
服务注册类型与注入请求的类型不匹配:
你在Program.cs中是以IApplicationState接口为服务标识、ApplicationState为实现类做的单例注册,此时DI容器中仅存在服务类型为IApplicationState的注册条目,并没有直接注册ApplicationState这个具体类型的服务。
但两个组件注入时写的是[Inject] ApplicationState ApplicationState { get; set; },直接向容器请求具体类ApplicationState的实例,容器找不到对应注册项,自然抛出服务未注册的异常。
修复方法
两种方案选其一即可,优先选第一种,符合依赖注入面向接口编程的最佳实践:
- 方案1:修改组件注入的类型,把两个组件里注入属性的类型从具体类
ApplicationState换成已注册的接口IApplicationState:
[Inject] IApplicationState ApplicationState { get; set; }
- 方案2:如果确实需要直接注入具体类,就调整服务注册代码。如果要同时支持接口和具体类两种注入方式、且拿到的是同一个单例,可以把原来的注册代码替换成:
// 注册具体类为单例 builder.Services.AddSingleton<ApplicationState>(); // 把接口映射到上面注册的单例实例 builder.Services.AddSingleton<IApplicationState>(sp => sp.GetRequiredService<ApplicationState>());
额外优化提示
PlateListComponent里订阅了状态类的OnPlateInput事件,一定要在组件销毁时解绑,否则会造成内存泄漏。需要让组件实现IDisposable接口,在Dispose方法中取消事件订阅:
partial class PlateListComponent : ComponentBase, IDisposable { // 保留原有代码不变 public void Dispose() { ApplicationState.OnPlateInput -= ApplicationState_OnPlateInput; } }
SideWidgetComponent里的SetPlateNumber是纯同步逻辑,没必要套Task.Run,会额外占用线程池资源,直接同步调用ApplicationState.SetPlateNumber即可。
内容的提问来源于stack exchange,提问作者Ibanez1408
相关产品推荐
相关产品推荐

