如何在非组件的自定义类中使用依赖注入(DI)?
在Blazor非组件类中使用依赖注入的解决方案
核心思路
非组件类无法直接使用@inject或[Inject]特性,必须通过依赖链传递注入或手动从服务容器获取两种方式使用DI,以下是具体实现方案:
方法一:构造函数注入(推荐,符合DI设计原则)
通过构造函数将依赖的服务从上层调用者传递进来,形成完整的依赖链,这是DI的标准用法。
示例场景:自定义业务类调用已注册的JsInteropForClasses
- 定义需要依赖注入的业务类,通过构造函数接收
JsInteropForClasses:
public class MyBusinessLogic { private readonly JsInteropForClasses _jsInterop; // 构造函数注入依赖服务 public MyBusinessLogic(JsInteropForClasses jsInterop) { _jsInterop = jsInterop; } public async Task ExecuteBusinessAction() { // 直接使用注入的服务实例 await _jsInterop.MessageBox(); } }
- 在
Program.cs中注册这个业务类(生命周期和JsInteropForClasses保持一致即可):
builder.Services.AddTransient<MyBusinessLogic>();
- 在组件中调用时,直接注入业务类即可,Blazor会自动解析整个依赖链:
@inject MyBusinessLogic BusinessService <button @onclick="ExecuteAction">触发JS弹窗</button> @code { private async Task ExecuteAction() { await BusinessService.ExecuteBusinessAction(); } }
方法二:手动从服务容器获取(仅应急场景使用)
如果遇到无法通过构造函数传递依赖的特殊场景(如静态方法、遗留代码),可以手动从IServiceProvider中获取服务,但这种方式会破坏DI的封装性,不推荐常规使用。
示例实现:
- 确保
JsInteropForClasses已在Program.cs中注册。 - 在需要使用的地方,先注入
IServiceProvider(组件中可直接注入),再创建作用域获取服务:
@inject IServiceProvider ServiceProvider <button @onclick="CallJsDirectly">直接调用JS弹窗</button> @code { private async Task CallJsDirectly() { // 创建作用域,避免生命周期不匹配问题 using var scope = ServiceProvider.CreateScope(); var jsInterop = scope.ServiceProvider.GetRequiredService<JsInteropForClasses>(); await jsInterop.MessageBox(); } }
如果是在非组件类中使用,需要先将IServiceProvider通过构造函数注入到该类中,再执行上述获取逻辑。
额外优化建议
你的MessageBox方法使用了async void,在Blazor中建议替换为async Task,避免异步操作引发的潜在问题:
public async Task MessageBox() { await jSRuntime.InvokeVoidAsync("MessageBox", "DI question!!!"); }
内容的提问来源于stack exchange,提问作者user20081580
相关产品推荐
相关产品推荐

