在 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);
}
}
);
但现在我需要修改将消耗 ServiceBusClient
或 ServiceBusAdministrationClient
的依赖项。
例如:
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
我们有一个微服务需要能够发送消息,不仅可以发送到多个主题,还可以发送到可能存在于不同 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);
}
}
);
但现在我需要修改将消耗 ServiceBusClient
或 ServiceBusAdministrationClient
的依赖项。
例如:
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