Reputation: 924
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
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