如何注入对特定IHostedService实现的引用? [英] How to inject a reference to a specific IHostedService implementation?

查看:333
本文介绍了如何注入对特定IHostedService实现的引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Web应用程序具有监听服务总线的后台服务.基于 docs ,看起来运行后台服务的内置方法是实现IHostedService.

My web app has a background service that listens to a service bus. Based on the docs, it looks like the built-in way to run a background service is to implement IHostedService.

所以我有一些看起来像这样的代码:

So I have some code that looks like this:

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,就可以使用新的便捷方法:

Once I update to ASP.NET 2.1 I can use the new convenience method:

services.AddHostedService<ServiceBusListener>();

但是我相信两者在功能上是等效的.

But I believe the two are functionally equivalent.

复杂之处::我的Web应用程序具有IHostedService的多种实现(特别是服务总线侦听器的不同实例).

The complication: my web app has multiple implementations of IHostedService (specifically, different instances of service bus listeners).

问题:我如何让其他组件获得对特定托管服务实现(我的服务总线侦听器)的引用?换句话说,如何将特定实例注入到组件中?

The question: how can I have some other component get a reference to a specific hosted service implementation (my service bus listener)? In other words, how do I get a specific instance injected into a component?

用例::我的后台服务侦听服务总线消息,然后将消息重新发布为.NET事件(如果您想知道,使用代码处理线程问题).如果事件在后台服务上,则订阅者需要获取对后台服务的引用才能进行订阅.

Use case: my background service listens for service bus messages and then re-publishes messages as .NET events (in case you're wondering, the consuming code deals with the threading issues). If the event is on the background service, then subscribers need to get a reference to the background service to be able to subscribe.

我尝试过的操作:如果我做了显而易见的事情,并将ServiceBusListener声明为要注入到其他组件中的依赖项,我的启动代码将抛出无法解析服务类型"例外.

What I've tried: if I do the obvious thing and declare ServiceBusListener as a dependency to be injected into a different component, my startup code throws a "Could not resolve a service of type" exception.

是否甚至可以请求IHostedService的特定实现?如果没有,最好的解决方法是什么?引入我的服务和消费者都可以引用的第三个组件吗?避免使用IHostedService并手动运行后台服务?

Is it even possible to request a specific implementation of a IHostedService? If not, what's the best workaround? Introduce a third component that both my service and the consumer can reference? Avoid IHostedService and run the background service manually?

推荐答案

结果证明有一种简单的方法(感谢指针,

Turns out there's an easy way to do this (thanks for the pointer, Steven).

如果您需要能够注入/获得对某些服务的引用,请继续正常注册该服务(无需担心任何IHostedService内容):

If you need to be able to inject / get a reference to some service, go ahead and register the service normally (without worrying about any IHostedService stuff):

services.AddSingleton<ServiceBusListener>();

现在我们可以注册一个单独的托管服务,其唯一责任是启动/停止我们刚刚注册的服务:

Now we can register a separate hosted service whose only responsibility is to start/stop the service we just registered:

services.AddHostedService<BackgroundServiceStarter<ServiceBusListener>>();

BackgroundServiceStarter是一个类似于以下内容的帮助器类:

Where BackgroundServiceStarter is a helper class that looks something like:

public class BackgroundServiceStarter<T> : IHostedService where T:IHostedService
{
    readonly T backgroundService;

    public BackgroundServiceStarter(T backgroundService)
    {
        this.backgroundService = backgroundService;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        return backgroundService.StartAsync(cancellationToken);
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return backgroundService.StopAsync(cancellationToken);
    }
}

更新2018/8/6 :由于 ygoe的建议,更新了代码以避免服务定位器模式

这篇关于如何注入对特定IHostedService实现的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆