如何注册 ServiceBusClient 以进行依赖注入?

Posted

技术标签:

【中文标题】如何注册 ServiceBusClient 以进行依赖注入?【英文标题】:How to register ServiceBusClient for dependency injection? 【发布时间】:2021-10-11 18:38:02 【问题描述】:

我正在尝试使用 ServiceBusClientBuilderExtensions 从新的 Azure.Messaging.ServiceBus 包中注册 ServiceBusClient 以进行依赖注入,如本 article 中所建议的那样,但我找不到任何文档或任何有关如何执行此操作的在线帮助。

我正在尝试添加如下

public override void Configure(IFunctionsHostBuilder builder)

    ServiceBusClientBuilderExtensions.AddServiceBusClient(builder, Typsy.Domain.Configuration.Settings.Instance().Connections.ServiceBusPrimary);

但我得到了错误

“Microsoft.Azure.Functions.Extensions.DependencyInjection.IFunctionsHostBuilder”类型必须可转换为“Azure.Core.Extensions.IAzureClientFactoryBuilder”才能在通用方法“IAzureClientBuilder Microsoft.Extensions.Azure.ServiceBusClientBuilderExtensions.AddServiceBusClient(this TBuilder, string)'

如果有人能帮上忙,那就太好了!

【问题讨论】:

【参考方案1】:

ServiceBusClientBuilderExtensions.AddServiceBusClientIAzureClientFactoryBuilder的扩展方法:

public static IAzureClientBuilder<ServiceBusClient, ServiceBusClientOptions> AddServiceBusClient<TBuilder>(this TBuilder builder, string connectionString)
            where TBuilder : IAzureClientFactoryBuilder

要获得IAzureClientFactoryBuilder 的实例,您需要为给定的IServiceCollection 调用AzureClientServiceCollectionExtensions.AddAzureClients(IServiceCollection, Action&lt;AzureClientFactoryBuilder&gt;),它提供了一个提供IAzureClientFactoryBuilder 实例的委托。 (此方法在Microsoft.Extensions.Azure NuGet 包中)

要调用该方法,您可以使用IFunctionsHostBuilder 提供的IServiceCollection。有了所有这些,您所拥有的应该如下所示:

public override void Configure(IFunctionsHostBuilder builder)

    builder.Services.AddAzureClients(clientsBuilder =>
    
        clientsBuilder.AddServiceBusClient(Typsy.Domain.Configuration.Settings.Instance().Connections.ServiceBusPrimary)
          // (Optional) Provide name for instance to retrieve by with DI
          .WithName("Client1Name")
          // (Optional) Override ServiceBusClientOptions (e.g. change retry settings)
          .ConfigureOptions(options =>
          
              options.RetryOptions.Delay = TimeSpan.FromMilliseconds(50);
              options.RetryOptions.MaxDelay = TimeSpan.FromSeconds(5);
              options.RetryOptions.MaxRetries = 3;
          );
    );

要检索命名实例,您可以使用IAzureClientFactory&lt;ServiceBusClient&gt;,而不是使用ServiceBusClient 作为注入类型。 无论您是否使用命名实例,ServiceBusClient 都是单例。

 public Constructor(IAzureClientFactory<ServiceBusClient> serviceBusClientFactory)
 
     // Wherever you need the ServiceBusClient
     ServiceBusClient singletonClient1 = serviceBusClientFactory.CreateClient("Client1Name")
 

【讨论】:

这如何与多个命名空间或连接字符串一起工作? @devNull 你也知道注册ServiceBusClient作为依赖的时候,是注册为单例吗?如果没有,您对我如何将其注册为单身人士有任何想法吗? 你知道在注册 ServiceBusClient 作为依赖项时如何传入 ServiceBusClientOptions 吗? 要从 ConfigureService 方法访问设置,您可以使用 var connectionString = Environment.GetEnvironmentVariable("ConnectionStrings:ServiceConnectionStrings"); - 参见微软关于环境变量的文章:docs.microsoft.com/en-us/azure/azure-functions/… @codea 使用上下文也可以是一个选项docs.microsoft.com/en-us/azure/azure-functions/…【参考方案2】:

对于那些只需要单个服务总线客户端的人来说,一个简单的单例就足够了

(使用 .Net 6 Azure Functions v4 测试):

using Azure.Messaging.ServiceBus;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using System;

[assembly: FunctionsStartup(typeof(YourProjName.Startup))]

namespace YourProjName

 public class Startup : FunctionsStartup
 
    public override void Configure(IFunctionsHostBuilder builder)
    
       
        var serviceBusConnectionString = Environment.GetEnvironmentVariable("ServiceBusConnectionString");
        if (string.IsNullOrEmpty(serviceBusConnectionString))
        
            throw new InvalidOperationException(
                "Please specify a valid ServiceBusConnectionString in the Azure Functions Settings or your local.settings.json file.");
        

        //using AMQP as transport
        builder.Services.AddSingleton((s) => 
            return new ServiceBusClient(serviceBusConnectionString, new ServiceBusClientOptions()  TransportType = ServiceBusTransportType.AmqpWebSockets ); 
        );

    
 

然后你可以在 Azure Function 构造函数中使用它:

public Function1(ServiceBusClient client)
   
       _client = client;
   

【讨论】:

【参考方案3】:

我想知道完全相同的事情,虽然我喜欢有一个专门的 azure 扩展,但我确实找到了另一种我更喜欢的方式,它看起来不那么复杂,希望这可以帮助其他人。

代码使用.AddSingleton Method 提供的函数委托。此函数委托将在构建的最后被调用,您可以在其中使用服务提供者并检索您的选项(如果我错了,请纠正我,因为文档既密集又稀疏:))。

以下是关键部分:

 serviceCollection.AddSingleton((serviceProvider) =>
            
                ServiceBusOptions options = serviceProvider.GetService<IOptions<ServiceBusOptions>>().Value;
                return new ServiceBusClient(options.ConnectionString);
            );

**完整代码 - 说得更多:) **

使用 Azure.Messaging.ServiceBus; 使用 Microsoft.Extensions.Configuration; 使用 Microsoft.Extensions.DependencyInjection; 使用 Microsoft.Extensions.Hosting; 使用 Microsoft.Extensions.Options;

命名空间 ConsoleJson.Example 类启动 私有静态 IHost DIHost;

    static void Main(string[] args)
    
        IHostBuilder hostbuilder = Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration(GetAppConfigurationDefinition);

        //Create Host (/build configuration)
        ConfigureSettings(hostbuilder);
        ConfigureServices(hostbuilder);

        DIHost = hostbuilder.Build();

        // Application code should start here.
        DIHost.Run();
    


    static void GetAppConfigurationDefinition(HostBuilderContext ctx, IConfigurationBuilder config)
    
        config.SetBasePath(Environment.CurrentDirectory)
       .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) // for simplicity appsettings.production.json / appsettings.development.json are not there.  This is where settings would go.
        .Build();
    

    public static void ConfigureServices(IHostBuilder hostbuilder)
    
        hostbuilder.ConfigureServices((hostContext, serviceCollection) =>
        

            serviceCollection.AddSingleton<ServiceBusClient>((serviceProvider) =>
            
                // options from appSettings.json
                // leverages IOptions Pattern to get an options object from the DIHost Service provider
                var myServiceBusOptions = serviceProvider.GetService<IOptions<ServiceBusOptions>>().Value;

                var sbClientOptions=new ServiceBusClientOptions()  
                TransportType=ServiceBusTransportType.AmqpTcp,
                RetryOptions=new ServiceBusRetryOptions()  Mode = ServiceBusRetryMode.Exponential 
                // ...
                ;

                // returns the ServiceBusClient Object configured per options we wanted
                return new ServiceBusClient(myServiceBusOptions.ConnectionString, sbClientOptions);
            );

        );
    

    public static void ConfigureSettings(IHostBuilder hostbuilder)
    
        hostbuilder.ConfigureServices((hostBuilderContext, serviceCollection) =>
        
            IConfiguration configurationRoot = hostBuilderContext.Configuration;
            serviceCollection.Configure<ServiceBusOptions>(configurationRoot.GetSection("ServiceBusOptions"));
        );
    

    public class ServiceBusOptions
    
        public string ConnectionString  get; set; 
    



AppSettings.Json

   
      "ServiceBusOptions": 
        "ConnectionString": ""
      
    

【讨论】:

以上是关于如何注册 ServiceBusClient 以进行依赖注入?的主要内容,如果未能解决你的问题,请参考以下文章

如何删除设计路线以进行注册?

如何在 ASP.NET MVC 6 中注册 ILogger 以进行注入

如何注册 GCM 和 APNS,获取 DeviceId 并将我的 API 发送给它以进行数据库存储?

如何以编程方式获取 Firebase 中的注册用户列表 [重复]

使用 pushsharp 获取 android 的注册 ID 以进行推送通知

Azure C# 框架 - 如何禁用验证代码以进行身份​​验证