3

在 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();
}

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

4

1 回答 1

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;

一个新的实例DefaultHttpClientBuilder被创建,它包装了IServiceCollection传入的那个。由于这是一个扩展方法,services这里指的services和你的ConfigureServices方法一样。然后通过 暴露出来IHttpClientBuilder.Services,这是您在引用 eg 时使用的内容myService1.Services

调用AddHttpContextAccessoruses TryAddSingleton,仅当服务尚未注册时才注册服务(source):

services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

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

于 2019-08-05T22:33:10.873 回答