【发布时间】:2018-12-17 15:21:18
【问题描述】:
我的网络应用有一个后台服务,它监听服务总线。基于docs,运行后台服务的内置方式似乎是实现IHostedService。
所以我有一些看起来像这样的代码:
public class ServiceBusListener : IMessageSource<string>, IHostedService
{
public virtual event ServiceBusMessageHandler<string> OnMessage = delegate { };
public Task StartAsync(CancellationToken cancellationToken)
{
// run the background task...
}
// ... other stuff ...
}
然后在Startup.cs 中注册服务:
services.AddSingleton<IHostedService, ServiceBusListener>();
一旦我更新到 ASP.NET 2.1,我就可以使用新的便捷方法:
services.AddHostedService<ServiceBusListener>();
但我相信两者在功能上是等价的。
复杂之处:我的网络应用程序有多个IHostedService 实现(具体来说,服务总线侦听器的不同实例)。
问题:如何让其他组件获得对特定托管服务实现(我的服务总线侦听器)的引用?换句话说,如何将特定实例注入到组件中?
用例:我的后台服务侦听服务总线消息,然后将消息作为 .NET 事件重新发布(如果您想知道,消费代码会处理线程问题)。如果事件在后台服务上,那么订阅者需要获取对后台服务的引用才能订阅。
我的尝试:如果我做了显而易见的事情并将ServiceBusListener 声明为要注入到不同组件中的依赖项,我的启动代码会抛出“无法解析类型”异常。
甚至可以请求IHostedService 的特定实现吗?如果没有,最好的解决方法是什么?引入我的服务和消费者都可以引用的第三个组件?避开IHostedService,手动运行后台服务?
【问题讨论】:
-
使用工厂方法并将依赖关系解析到您的类中,并在工厂方法中新建它。当它有许多构造函数参数时可能会变得乏味。或者使用第 3 方解析器。最后但并非最不重要的一点是,您可以使用 ActivatorUtils.CreateInstance 方法将依赖项替换为合适的对象(您需要在工厂方法中解决一些 where 或 new 它(取决于您的情况,哪个最适合)。docs.microsoft.com/en-us/dotnet/api/…跨度>
-
另外 "Could not resolve a service of type" exception 那是因为你没有注册它:P 你只注册了 IHostedService => ServiceBusListener,没有 ServiceBusListener =>服务总线监听器
-
为什么要获得对托管服务的引用?托管服务旨在自行在后台运行。也许您只需要创建一个接口并注册一个单例,然后您就可以在需要的地方注入它?
-
@Steven:我喜欢这个主意。也许有一个实现 IHostedService 的启动类,它知道如何委托给我单独注册的单例(使用我的理想接口)。
标签: asp.net-core dependency-injection