2

We have a microservice which needs to be able to send messages, not only to multiple Topics but to Topics which may live on different Azure Service Buses.

In other words, one Topic ("Foo") might need to be accessed by the connection string: Endpoint=sb://foo.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=45346346346346346weffv34f43fc32c3d3d23=

and another ("Bar") might need to be accessed by the connection string: Endpoint=sb://bar.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=sdvc243r4f4f32c3cd32c23dc2332c2332re=

I'm using the following model to get the connection strings out of the appsettings or Azure portal configuration:

public class MultiServiceBusSettings
{
    public List<string> ConnectionStrings { get; init; }

    private readonly Regex ConnectionStringPattern = new(@"(?:sb:\/\/)(.*)(?:\/)",
            RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase
        );

    private Dictionary<string, string> _connectionStringsBySubdomain;

    private Dictionary<string, string> ConnectionStringsBySubdomain
    {
        get
        {
            if (_connectionStringsBySubdomain == null)
            {
                _connectionStringsBySubdomain = ConnectionStrings.ToDictionary(x =>
                {
                    Match match = ConnectionStringPattern.Match(x);
                    return match.Success
                        ? match.Groups[1].Value
                        : throw new ArgumentException($"Invalid connection string: {x}");

                });
            }

            return _connectionStringsBySubdomain;
        }
    }

    public string this[string subdomain] =>
        ConnectionStringsBySubdomain[subdomain];
}

And then using the following to add the clients to the solution:

        MultiServiceBusSettings settings = Configure<MultiServiceBusSettings>(services, configuration, configSectionName);
        services.AddAzureClients(builder =>
        {
            foreach (string connectionString in settings.ConnectionStrings)
            {
                _ = builder.AddServiceBusClient(connectionString);
                _ = builder.AddServiceBusAdministrationClient(connectionString);
            }
        }
        );

But now I need to modify the dependencies which will consume either the ServiceBusClient or ServiceBusAdministrationClient.

For example:

public class ServiceBusMessageSender : IMessageSender
{
    private readonly ServiceBusClient _serviceBusClient;

    public ServiceBusMessageSender(ServiceBusClient serviceBusClient) =>
        _serviceBusClient = serviceBusClient ?? throw new ArgumentNullException(nameof(serviceBusClient));

    // Snipped for brevity

If I don't somehow tell the system which instance of ServiceBusClient to inject, I would expect the methods to at least occasionally fail.

What would be the best (or at least a good) way to fix this?

2
  • 1
    You can use named registrations to accomplish this: github.com/Azure/azure-sdk-for-net/blob/… You would then inject the IAzureClientFactory<ServiceBusClient> which would allow you to create the individual named clients: github.com/Azure/azure-sdk-for-net/blob/… Commented May 5, 2022 at 4:32
  • 1
    @JoshLove, cheers for the response. Since posting my question, I've already figured that out, but if you wish to make a proper answer, I'll be happy to accept it. :-) Commented May 5, 2022 at 9:14

1 Answer 1

1

You can use named registrations to accomplish this, e.g https://github.com/Azure/azure-sdk-for-net/blob/4162f6fa2445b2127468b9cfd080f01c9da88eba/sdk/extensions/Microsoft.Extensions.Azure/samples/Startup.cs#L39

You would then inject the IAzureClientFactory which would allow you to create the individual named clients: https://github.com/Azure/azure-sdk-for-net/blob/4162f6fa2445b2127468b9cfd080f01c9da88eba/sdk/extensions/Microsoft.Extensions.Azure/samples/Startup.cs#L71

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.