在 C# 中,当向服务添加多个服务总线客户端或管理客户端时,我们如何才能从服务提供者那里取回正确的客户端?

In C#, when adding multiple service bus clients or administration clients to services, how can we get the correct one back from the service provider?

我们有一个微服务需要能够发送消息,不仅可以发送到多个主题,还可以发送到可能存在于不同 Azure 服务总线上的主题。

换句话说,连接字符串可能需要访问一个主题(“Foo”): 端点=sb://foo.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=45346346346346346weffv34f43fc32c3d3d23=

和另一个(“Bar”)可能需要通过连接字符串访问: 端点=sb://bar.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=sdvc243r4f4f32c3cd32c23dc2332c2332re=

我正在使用以下模型从应用程序设置或 Azure 门户配置中获取连接字符串:

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];
}

然后使用以下方法将客户端添加到解决方案中:

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

但现在我需要修改将消耗 ServiceBusClientServiceBusAdministrationClient 的依赖项。

例如:

public class ServiceBusMessageSender : IMessageSender
{
    private readonly ServiceBusClient _serviceBusClient;

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

    // Snipped for brevity

如果我不以某种方式告诉系统要注入 ServiceBusClient 的哪个实例,我希望这些方法至少偶尔会失败。

解决此问题的最佳(或至少是好的)方法是什么?

您可以使用命名注册来完成此操作,例如 https://github.com/Azure/azure-sdk-for-net/blob/4162f6fa2445b2127468b9cfd080f01c9da88eba/sdk/extensions/Microsoft.Extensions.Azure/samples/Startup.cs#L39

然后您将注入 IAzureClientFactory,这将允许您创建单独的命名客户端:https://github.com/Azure/azure-sdk-for-net/blob/4162f6fa2445b2127468b9cfd080f01c9da88eba/sdk/extensions/Microsoft.Extensions.Azure/samples/Startup.cs#L71