依赖注入注册类能否无需构造函数引用实例化并后台运行?
解决方案:用ASP.NET Core后台服务自动初始化你的ObjectBus
你想要的效果其实完全可以通过ASP.NET Core内置的**后台服务(Hosted Service)**实现,不用再在业务类的构造函数里注入一个根本用不上的依赖,就能让IObjectBus<T>自动实例化并建立好连接。
具体怎么做?
1. 写个通用的后台初始化服务
先搞一个泛型的后台服务类,它的唯一作用就是在应用启动时从DI容器里把IObjectBus<T>捞出来,触发它的初始化逻辑:
public class ObjectBusInitializer<T> : BackgroundService { private readonly IServiceProvider _serviceProvider; public ObjectBusInitializer(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { // 因为你的IObjectBus是Scoped的,所以要先创建一个服务范围 using var scope = _serviceProvider.CreateScope(); // 从范围里获取实例,这一步就会触发DI创建对象、执行构造逻辑(包括建立连接) var objectBus = scope.ServiceProvider.GetRequiredService<IObjectBus<T>>(); // 如果你的ObjectBus有专门的初始化方法(比如OpenConnection),可以在这里主动调用 // 不过根据你的描述,实例化时已经会自动建连接,所以这步可能不用额外操作 // 让服务一直挂着直到应用关闭,避免实例被回收 await Task.Delay(Timeout.Infinite, stoppingToken); } }
2. 在ConfigureServices里注册这个后台服务
在你原来的CreateObjectBus调用之后,把这个后台服务也注册进去:
// 原来的ObjectBus注册逻辑不变 services.CreateObjectBus<RecordingChunk>(p => p.Configure( Configuration["AzureServiceBus:ConnectionString"], Queues.Editor, ObjectBus.BusType.Sender)); // 注册后台初始化服务,应用启动时会自动触发IObjectBus<RecordingChunk>的实例化 services.AddHostedService<ObjectBusInitializer<RecordingChunk>>();
如果还有其他类型的IObjectBus(比如你提到的IObjectBus<Podcast>),只需要再注册一个对应的初始化服务就行:
services.AddHostedService<ObjectBusInitializer<Podcast>>();
为什么这方案好使?
- ASP.NET Core的Hosted Service是官方提供的后台运行机制,应用一启动就会自动启动这些服务,
ExecuteAsync方法会被调用,这时我们获取IObjectBus<T>实例的动作,会让DI自动创建对象并执行它的构造逻辑(包括你需要的数据库、服务总线连接建立)。 - 完全不用在任何业务类的构造函数里注入
IObjectBus<T>,避免了那种“注入了却根本不用”的尴尬代码,保持业务逻辑的清爽。 - 后台服务会一直运行到应用关闭,确保
IObjectBus<T>的实例在整个应用生命周期内都能正常工作(如果你的ObjectBus是Singleton的,也可以调整获取实例的方式,不用创建服务范围)。
额外小技巧:封装成扩展方法简化注册
如果你有好多个IObjectBus要初始化,可以写个扩展方法,让代码更简洁:
public static class ObjectBusHostedServiceExtensions { public static IServiceCollection AddObjectBusInitializer<T>(this IServiceCollection services) { services.AddHostedService<ObjectBusInitializer<T>>(); return services; } }
之后注册的时候就可以链式调用:
services.CreateObjectBus<RecordingChunk>(...) .AddObjectBusInitializer<RecordingChunk>();
内容的提问来源于stack exchange,提问作者Adam Young
相关产品推荐
相关产品推荐

