ConfigureServices 中的 AddHttpContextAccessor 与每个 HttpClient

Joh*_*ohn 3 c# asp.net-core httpclientfactory

在 ConfigureServices 方法中一次添加 httpContextAccessor 与为每个 HttpClient 配置添加 HttpContextAccessor 之间有什么区别。

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    // FIRST VERSION
    services.AddHttpContextAccessor();

    // SECOND VERSION
    var myService1 = services.AddHttpClient<TestHttpClient1>(c =>
    {
        c.BaseAddress = new Uri(Configuration["TestHttpClient1"]);
    });
    myService1.Services.AddHttpContextAccessor();

    var myService2 = services.AddHttpClient<TestHttpClient2>(c =>
    {
        c.BaseAddress = new Uri(Configuration["TestHttpClient2"]);
    });
    myService2.Services.AddHttpContextAccessor();
}
Run Code Online (Sandbox Code Playgroud)

我的猜测是认为在第二个版本中,我们有两个单例,一个用于类 TestHttpClient1,另一个用于 TestHttpClient2 但我不明白为什么要这样做,因为我在生产中看到了这段代码。

Kir*_*kin 5

在 ConfigureServices 方法中一次添加 httpContextAccessor 与为每个 HttpClient 配置添加 HttpContextAccessor 之间有什么区别。

不,没有任何区别。myService1.Services并且myService2.Services都引用 变量相同IServiceCollection的内容services。第一个调用 ( services.AddHttpContextAccessor()) 将注册服务,但接下来的两个调用 (myService1.Services.AddHttpContextAccessor()myService2.Services.AddHttpContextAccessor()) 将无操作(什么都不做)。

为了将所有内容放在上下文中,以下是AddHttpClient<TClient>(...)( source )的源代码的摘录:

var builder = new DefaultHttpClientBuilder(services, name);
// ...
return builder;
Run Code Online (Sandbox Code Playgroud)

一个新的实例DefaultHttpClientBuilder被创建,它包装了IServiceCollection传入的。由于这是一个扩展方法,services这里指的与services你的ConfigureServices方法中的相同。然后通过 公开IHttpClientBuilder.Services,这就是您在引用 eg 时使用的内容myService1.Services

AddHttpContextAccessoruses的调用TryAddSingleton,只有在服务尚未注册()时才会注册该服务:

services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
Run Code Online (Sandbox Code Playgroud)

在您的示例中,它已经在第一次调用 时注册services.AddHttpContextAccessor(),这意味着接下来的两次注册尝试什么也不做。