【问题标题】:Can't bind service implementation using DI inside function with ServiceBusTrigger parameter in .net core Azure Web Job无法在.net core Azure Web Job中使用带有ServiceBusTrigger参数的DI内部函数绑定服务实现
【发布时间】:2020-03-15 16:21:55
【问题描述】:

我有一个要部署为 Azure Web 作业的 .net 核心控制台应用程序。该作业的目的是侦听 Azure 服务总线队列中的新消息。我已经使用包含 [ServiceBusTrigger] 属性的函数设置了侦听器。我构建了一个虚拟实现,它只从队列中读取最新消息 - 这没有问题 - 消息从服务总线队列正确传递到我的函数。

当我尝试进入下一个级别并向要由 DI 注入的函数添加接口参数时,出现错误。

Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexingException: '错误索引方法'Functions.ProcessMeasurementData'' InvalidOperationException:无法将参数“服务”绑定到类型 IProcessMeasurementService。确保支持参数类型 通过绑定。如果您使用绑定扩展(例如 Azure Storage、ServiceBus、Timers 等)确保你已经调用了 启动代码中扩展的注册方法(例如 builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers() 等)。

这是我的功能。如果我删除参数 IProcessMeasurementService 服务,它可以在 Visual Studio 2019 本地运行没有问题(我还没有尝试部署到 azure 作为 web 作业),在添加到 Azure 服务总线队列时拾取新项目。

public class Functions
{
    public static async Task ProcessMeasurementData(
        [ServiceBusTrigger("process-measurement-data-queue", Connection = "AzureWebJobsServiceBus")] Message message,
    IProcessMeasurementService service)
    {
        try
        {

            var measurements = JsonConvert
                .DeserializeObject<List<CreateMeasurementInput>>
                    (Encoding.UTF8.GetString(message.Body));

            await service.DoStuff(measurements);

            // log.LogInformation(message.ContentType);
        }
        catch (Exception e)
        {

            throw;
        }
    }

我认为我正在正确注册服务,如下所示:

            {
                // Register application services
                services.AddSingleton<IProcessMeasurementService, ProcessMeasurementService>();
            });

这是我的全部主要功能。

        static void Main(string[] args)
    {
        var builder = new HostBuilder();

        builder.ConfigureAppConfiguration((builder) =>
        {
            builder

                .AddJsonFile("appsettings.json", false, true)
                .AddEnvironmentVariables();
        });


        builder.ConfigureWebJobs(b =>
        {
            b.AddServiceBus(x =>
            {
                x.MessageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
                {
                    AutoComplete = false
                };
            });

            b.AddAzureStorageCoreServices();
        });

        builder.ConfigureServices(services =>
        {
            services.AddOptions();

            // Register application services
            services.AddSingleton<IProcessMeasurementService, ProcessMeasurementService>();
        });

        var host = builder.Build();

        using (host)
        {
            host.Run();
        }
    }

通过谷歌搜索感觉问题可能与我的 nuget 包版本有关。我尝试添加一个名为“host.json”的文件,以防 azure 函数版本与扩展库冲突的已知问题。但它什么也没做。我实际上并没有使用 AzureFunctions(我的意思是无服务器函数),但在这个阶段我正抓着稻草。

有谁知道问题出在哪里?

这是 host.json 以防万一这是问题。

{
  "version": "2.0",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[1.*, 2.0.0)"
  }
}

这是我安装的 nuget 版本

<PackageReference Include="Microsoft.Azure.ServiceBus" Version="4.1.2" />
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.16" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="4.1.1" />
<PackageReference Include="Microsoft.Azure.WebJobs.Sources" Version="3.0.16" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" />

【问题讨论】:

    标签: .net-core dependency-injection azureservicebus azure-webjobs azure-servicebus-queues


    【解决方案1】:

    从静态函数方法更改为实例成员,并通过构造函数注入将服务直接注入函数类。

    public class Functions {
    
        private readonly  IProcessMeasurementService service;
    
        public Functions (IProcessMeasurementService service) {
            this.service = service;
        }
    
        public async Task ProcessMeasurementData(
            [ServiceBusTrigger("process-measurement-data-queue", Connection = "AzureWebJobsServiceBus")] Message message) 
        {
            try {
    
                var measurements = JsonConvert
                    .DeserializeObject<List<CreateMeasurementInput>>
                        (Encoding.UTF8.GetString(message.Body));
    
                await service.DoStuff(measurements);
    
                // log.LogInformation(message.ContentType);
            } catch (Exception e) {
                //...    
                throw;
            }
        }
    }
    

    【讨论】:

    • 你是对的有两个原因:1 - 你不能在静态类中使用依赖注入; 2 - 即使可以,也不能直接在其方法上进行注入,必须通过构造函数。但是,我应该补充一点,有些人认为(这不是共识)Azure Functions 必须是静态的:stackoverflow.com/questions/45168659/…
    猜你喜欢
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 2019-10-22
    • 2021-04-05
    • 1970-01-01
    • 2021-03-28
    • 1970-01-01
    相关资源
    最近更新 更多