Joerg
Joerg

Reputation: 924

How to create and inject multiple ServiceBusReceiver singletons similar to named ServiceBusClients when using Azure Service Bus?

I am writing applications (Asp.net Web API / Worker Services) that use multiple BackgroundServices which listen to various Azure Service Bus queues and/or topics.

The documentation recommends

The Service Bus objects that interact with the service, such as ServiceBusClient, ServiceBusSender, ServiceBusReceiver, and ServiceBusProcessor, should be registered for dependency injection as singletons (or instantiated once and shared). [...] We recommend that you don't close or dispose these objects after sending or receiving each message.

Fair enough, so I added this to my startup code:

services.AddAzureClients(builder =>
{
    builder.AddServiceBusClient(myConnectionString);
});

But what should I do with the various ServiceBusReceiver instances? Without dependency injection, I would do:

ServiceBusReceiver receiverA = client.CreateReceiver("queue-a");
ServiceBusReceiver receiverB = client.CreateReceiver("queue-b");
ServiceBusReceiver receiverC = client.CreateReceiver("queue-c");

Do I have to create and register a separate singleton wrapper class for each of the ServiceBusReceiver instances? Or is there an easier way similar to named ServiceBusClients?

P.S.: I also have the analogous question for ServiceBusSender instances. In case that is somehow different in nature.

Upvotes: 2

Views: 1226

Answers (1)

J.Loscos
J.Loscos

Reputation: 2917

If you don't want to create wrappers a solution could be to register a delegate in the dependency injection.

You start by defining a delegate that returns a ServiceBusReceiver based on a name :

public delegate ServiceBusReceiver ServiceBusReceiverResolver(string name);

Then you can register an implementation of the delegate that return the receiver related to the name

ServiceBusReceiver receiverA = client.CreateReceiver("queue-a");
ServiceBusReceiver receiverB = client.CreateReceiver("queue-b");
ServiceBusReceiver receiverC = client.CreateReceiver("queue-c");

builder.Services.AddSingleton<ServiceBusReceiverResolver>(name => name switch
{
    "queue-a" => receiverA,
    "queue-b" => receiverB,
    "queue-C" => receiverC,
    _ => throw new InvalidOperationException($"Unknown receiver {name}")
});

You now can inject the delegate into your services and use it to get the receiver you need :

public class MyService
{
    private readonly ServiceBusReceiver receiver;
    public MyService(ServiceBusReceiverResolver resolver)
    {
        receiver = resolver("queue-b");
    }
}

Upvotes: 0

Related Questions