无法在 .net 核心 Azure Web 作业中使用带有 ServiceBusTrigger 参数的 DI 内部函数绑定服务实现

Can't bind service implementation using DI inside function with ServiceBusTrigger parameter in .net core Azure Web Job

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

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

Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexingException: 'Error indexing method 'Functions.ProcessMeasurementData'' InvalidOperationException: Cannot bind parameter 'service' to type IProcessMeasurementService. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).

这是我的职责。如果我删除参数 IProcessMeasurementService 服务,它从 Visual Studio 2019 开始在本地 运行 正常工作(我还没有尝试部署到 azure 作为 webjob),在将新项目添加到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" />

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

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