使用 services.AddHttpClient 时,HttpClient 是在哪里创建的?

When using services.AddHttpClient, where is the HttpClient created?

我正在尝试了解如何在 Nop Commerce 中为验证码实施 HttpClient,以及为了可测试性,如何在 Nop Commerce 项目中管理创建 HttpClient 的新实例。

我遇到了 ValidateCaptchaAttributeValidateCaptchaFilter 我看到 HttpClient 已经被包裹在里面 CaptchaHttpClient class 但我不明白 CaptchaHttpClient 从哪里接收 HttpClient 的依赖关系以及从哪里调用 CaptchaHttpClient class 的构造函数。

里面 ServiceCollectionExtensions class 我看到下面的代码:

public static void AddNopHttpClients(this IServiceCollection services)
 {
    //default client
    services.AddHttpClient(NopHttpDefaults.DefaultHttpClient).WithProxy();

    //client to request current store
    services.AddHttpClient<StoreHttpClient>();

    //client to request nopCommerce official site
    services.AddHttpClient<NopHttpClient>().WithProxy();

    //client to request reCAPTCHA service
    services.AddHttpClient<CaptchaHttpClient>().WithProxy();
 }

但我看不到 HttpClient 对象的创建位置:

var client = new HttpClient() // Where this is done?

我是不是漏掉了什么?

Nop 商务版 = 4.20

来自 the documentation:

Adds the IHttpClientFactory and related services to the IServiceCollection and configures a binding between the TClient type and a named HttpClient. The client name will be set to the type name of TClient.

粗略翻译,services.AddHttpClient<CaptchaHttpClient>() 表示 CaptchaHttpClient 依赖于 HttpClient。这表示当将 HttpClient 注入 CaptchaHttpClient 时,不要只是创建一个新的 - 使用 IHttpClientFactory 的实现来提供一个并注入它。

这意味着您没有管理 HttpClient 的生命周期。 ServiceProvider 正在幕后进行。

This documentation 解释了为什么它存在以及它是如何工作的。

A Typed Client is, effectively, a transient object, meaning that a new instance is created each time one is needed and it will receive a new HttpClient instance each time it's constructed. However, the HttpMessageHandler objects in the pool are the objects that are reused by multiple Http requests.

这意味着:

  • 您正在注册的东西 - 在这种情况下 CaptchaHttpClient 是暂时的,因此每次解析时都会创建一个新实例。
  • 每次创建时,都会创建并注入一个新的HttpClient
  • 虽然HttpClient是新的,但是它所依赖的HttpMessageHandler是重用的。

这使用了我们不需要管理的 HttpMessageHandler 个实例池。我们的 class 只依赖于 HttpClient,而不必担心每次我们需要 create/dispose 和 HttpClient 时发生的负面影响。

我发现 this article 有助于加深我对 IHttpClientFactory 模式的理解。

When defining typed clients in your ConfigureServices method, the typed service is registered with transient scope. This means that a new instance is created by the DI container every time one is needed. The reason this occurs is that a [sic] HttpClient instance is injected into the typed client instance. That HttpClient instance is intended to be short lived so that the HttpClientFactory can ensure that the underlying handlers (and connections) are released and recycled.