Azure Functions 中的依赖注入无法为类型化的 HttpClient 调用配置委托?

Dependency injection in Azure Functions fails to invoke configuration delegate for a typed HttpClient?

我有以下 class:

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

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

namespace MyNamespace
{
public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddHttpClient<SomeAzureFunction>(c =>
        {
          // some code
        });
    }
}
}

委托 c => { // some code } 从未真正被调用过?怎么回事?

Microsoft clearly states 他们在此示例中使用 Microsoft.Extensions.Http

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

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

namespace MyNamespace
{
public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddHttpClient();

        builder.Services.AddSingleton<IMyService>((s) => {
            return new MyService();
        });

        builder.Services.AddSingleton<ILoggerProvider, MyLoggerProvider>();
    }
}
}

我的用法唯一不同的是,我不是简单地注册 IHttpClientFactory,而是注册一个类型化的客户端。

azure 函数带有定时器触发器。

SomeAzureFunction 的签名如下:

public SomeAzureFunction(HttpClient httpClient)

编辑: 似乎如果我将构造函数更改为接受 IHttpClientFactory 然后对其执行以下操作:IHttpClientFactory.CreateClient(nameof(SomeAzureFunction)) 它最终决定执行委托,但我不明白为什么在我注入 HttpClient.

时它不会自动执行

要了解这里发生了什么,我们需要更深入地研究一下。这与 Azure Functions 无关,与依赖注入和类型化客户端注册为瞬态服务的方式有关。

类型化客户端的类型确实在 DI 容器中注册为临时服务,但它正在注册 Func<IServiceProvider, TService> implementationFactory delegate。只有当类型被传递到依赖注入的构造函数时才会调用该委托(即它被用于 DI)。

这意味着如果我们有一个类型 A,并且我们通过 IServiceCollection.AddHttpClient<A>() 将该类型注册为类型化客户端,那么如果我们在任何 Azure Functions 中传递 A构造函数或控制器(用于 Web 应用程序),它将按我们预期的方式解析 - A 内的 HttpClient 将成功成为 DI.

但我们实际上不希望在其他构造函数中传递 A。我们希望 A 简单地对“输入的”HttpClient 进行 DI。然后我们只需要在 IServiceCollection 中使用适当的范围注册类型 A 。我们通过调用 IServiceCollection.AddTransient<A>();.

来做到这一点

我说“类型化”,因为本质上,我上面提到的那个代表实际上就是“类型化”HttpClient 的全部内容。实际上 - 每个 HttpClient 注册的都是一个“命名”客户端 - 包括 Typed 个客户端。它们只会带来将命名的 HttpClient 注册到您定义的类型的好处,因此您可以对该类型使用依赖注入,而不是用注入 IHttpClientFactory 的经典方式来代替,然后调用 IHttpClientFactory.CreateClient("namedClient");

“类型”的名称 HttpClient 是您类型的名称。如果您这样做 IServiceCollection.AddHttpClient<HelloWorld>();,命名的客户端将被称为“HelloWorld”。

我无法理解为什么 通过 Func<IServiceProvider, TService> 委托注册的服务会以这种方式运行,所以如果有人提供更多详细信息,我将不胜感激。