【问题标题】:Create one HTTP Client per API每个 API 创建一个 HTTP 客户端
【发布时间】:2019-06-06 17:34:06
【问题描述】:

我有许多名为 DataAdapter 的类,它们位于不同的文件夹中,每个类都包含一个唯一配置的 HttpClient 以访问外部 API。我使用反射创建了DataAdapter 类的正确版本。

下面的例子:

internal class DataAdapter : IDataAdapter
{
    public HttpClient Client => GetClient();

    static HttpClient GetClient()
    {
        // This implementation is unique to the API
        var client = new HttpClient();
        client.AcceptHeader(MediaType.Json);
        client.AuthorizationHeader("123456");
        client.Timeout = TimeSpan.FromSeconds(300);
        return client;

    }
}

这里的前提是为每个 API 创建一个HttpClient。因此,当第二个用户出现并实例化一个新的DataAdapter 类(在同一文件夹中)时,他们应该重用相同的HttpClient

如果用户在不同的文件夹中实例化 new DataAdapter 类,则应创建不同版本的 HttpClient(如果尚不存在)。

我不确定的是方法中的new HttpClient - 每次实例化这个确切类的新实例时,该示例是否会返回new HttpClient,还是只会创建一个?

【问题讨论】:

  • 该方法是静态的,但Client 不是。所以每次创建DataAdapter 时,每个实例都会调用静态方法,创建一个新的HttpClient。您是否有机会使用IServiceCollection 并注入DataAdapter?这种情况有一个很好的解决方案。
  • 不,这是自定义解决方案。我知道有一些关于重用 HttpClients 的新内容,但除了示例中显示的内容之外,还有更多内容。
  • 您可以将依赖注入与自定义解决方案一起使用。并不是说我一定要为此添加它。但在这种情况下,您可以这样做:serviceCollection.AddHttpClient<DataAdapter>();,然后将HttpClient 注入DataAdapter 的构造函数中。然后你在你的班级中设置你的标题等。容器将管理HttpClient 的创建方式,您无需在课堂上处理它。
  • 感谢您提供的信息 - 我昨天简要地看了这个。它为我的项目添加了大约 20 个包,但我觉得这有点矫枉过正。不过,如果没有更简单的解决方案,我会重新考虑。
  • HttpClient 可能会令人困惑,请务必了解这些最佳实践,以便正确实施blogs.msdn.microsoft.com/shacorn/2016/10/21/…

标签: c# asp.net static


【解决方案1】:

每次访问该属性时,原始代码都会创建一个新的HttpClient。使用以下代码将在第一次需要时创建一个,然后返回相同的:

internal class DataAdapter : IDataAdapter
{
    public HttpClient Client => staticClient.Value;

    static Lazy<HttpClient> staticClient = new Lazy<HttpClient>(()=>
    {
        // This implementation is unique to the API
        var client = new HttpClient();
        client.AcceptHeader(MediaType.Json);
        client.AuthorizationHeader("123456");
        client.Timeout = TimeSpan.FromSeconds(300);
        return client;    
    });
}

这个想法是 Lazy&lt;T&gt; 属性为您提供了一些东西。它会延迟HttpClient 的实例化,直到需要它为止;并且,它提供了线程安全,没有任何大惊小怪。使用 static Lazy&lt;T&gt; 意味着你得到一个单例 HttpClient 每个 DataAdapter 类,及时初始化;这听起来像是您正在尝试做的事情。

基本上,当您请求 client.Value 时,Lazy&lt;T&gt; 第一次将使用提供的委托创建 HttpClient,并在第二次记住该值 - 同时为您提供线程安全。

【讨论】:

  • 抱歉耽搁了,正在测试中。它似乎做我想做的事。
猜你喜欢
  • 2021-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-03
  • 1970-01-01
  • 2021-11-21
相关资源
最近更新 更多