在ASP.net Core中注入多个ServiceBusClient

Aam*_*mir 7 .net c# dependency-injection azure-web-app-service asp.net-core

我想注入多个具有相同连接字符串但不同队列名称的 ServiceBusClient。

    _services.TryAddSingleton(implementationFactory =>
    {
        var serviceBusConfiguration = implementationFactory.GetRequiredService<Microsoft.Extensions.Options.IOptions<UserEventConsumerSetting>>().Value;
    
        var serviceBusClient = new ServiceBusClient(serviceBusConfiguration.ServiceBusConnectionString, new ServiceBusClientOptions
        {
            TransportType = ServiceBusTransportType.AmqpWebSockets
        });
    
        return serviceBusClient.CreateReceiver(serviceBusConfiguration.ServiceBusQueueName, new ServiceBusReceiverOptions
        {
            ReceiveMode = ServiceBusReceiveMode.PeekLock
        });
    });
Run Code Online (Sandbox Code Playgroud)

为了使用我必须创建 ServiceBusSender 实例。

    private readonly ServiceBusSender _serviceBusSender;
    
    public CarReservationMessagingService(ServiceBusSender serviceBusSender)
    {
        _serviceBusSender = serviceBusSender ?? throw new ArgumentNullException(nameof(serviceBusSender));
    }
    
    public async Task PublishNewCarReservationMessageAsync(CarReservation carReservation)
    {
        var carReservationIntegrationMessage = new CarReservationIntegrationMessage
        {
            Id = Guid.NewGuid().ToString(),
            CarId = carReservation.CarId,
            CustomerId = carReservation.CustomerId,
            RentFrom = carReservation.RentFrom,
            RentTo = carReservation.RentTo
        };
    
        var serializedMessage = JsonSerializer.Serialize(carReservationIntegrationMessage);
        ServiceBusMessage message = new ServiceBusMessage(serializedMessage);
        await _serviceBusSender.SendMessageAsync(message);
    }
Run Code Online (Sandbox Code Playgroud)

如何注入多个 servicebusclient 并以不同的方式使用它们?

小智 11

对于将来来到这里的任何人,我建议使用ServiceBusClientBuilderExtensions

public override void Configure(IFunctionsHostBuilder builder)
{
    builder.Services.AddAzureClients(clientsBuilder =>
    {
        clientsBuilder.AddServiceBusClient("Client1ConnectionString")
          .WithName("Client1Name");
        clientsBuilder.AddServiceBusClient("Client2ConnectionString")
          .WithName("Client2Name");
    });
}
Run Code Online (Sandbox Code Playgroud)

为了检索它,您必须使用IAzureClientFactory<ServiceBusClient>以下命令:

 public Constructor(IAzureClientFactory<ServiceBusClient> serviceBusClientFactory)
 {
     ServiceBusClient client1 = serviceBusClientFactory.CreateClient("Client1Name")
 }
Run Code Online (Sandbox Code Playgroud)

从此答案中获取并简化的代码片段。


Tem*_*Tre 1

因此,在其他 IoC 容器(如 Unity)中,可以指定命名依赖项。您在注册时指定名称,如下所示:

container.RegisterSingleto<SomeClassImplementation>("Name")
Run Code Online (Sandbox Code Playgroud)

然后在您使用的类中,您应该指定具有此名称的属性

[DependencyAttribute("Name")]
Run Code Online (Sandbox Code Playgroud)

但.net core中没有这样的功能。您可以使用统一。或者您可以对此功能进行一些模仿。

让我们创建枚举(如果需要,也可以创建常量)

enum ServiceBusQueue { ServiceBus1, ServiceBus2, ServiceBus3}
Run Code Online (Sandbox Code Playgroud)

然后创建服务buc提供者

public class ServiceBusQueueProvider
{
    private Dictionary<ServiceBusQueue, ServiceBusSender > _senders;

    public ServiceBusQueueProvider()
    {
        //Method to initialize all queues with all names and store it in _senders;
    }

    public ServiceBusSender Resolve(ServiceBusQueue queue)
    {
        return _senders[queue];
    }
}
Run Code Online (Sandbox Code Playgroud)

然后注册这个提供者并在您需要获得不同队列的其他类中使用它:

 _services.TryAddSingleton(implementationFactory => ServiceBusQueueProvider());
Run Code Online (Sandbox Code Playgroud)

并在构造函数中:

public SomeClass(ServiceBusQueueProvider provider)
{
    _serviceBusSender  = provider.Resolve(ServiceBusQueue.ServiceBus1);
}
Run Code Online (Sandbox Code Playgroud)

还有一点是,您应该更改 MessagingServiceConfiguration 这个类映射到配置。在当前的实现中,您只能指定一个队列。将其更改为:

public class MessagingServiceConfiguration
{
    public List<MessagingServiceConfigurationItem> Queues { get; set; }
}

public class MessagingServiceConfigurationItem
{
    public string QueueName { get; set; }
    public string ListenAndSendConnectionString { get; set; }
}
Run Code Online (Sandbox Code Playgroud)