C# 类型化HttpClient vs IHttpClient Factory

C# 类型化HttpClient vs IHttpClient Factory,c#,asp.net-core,dotnet-httpclient,httpclientfactory,C#,Asp.net Core,Dotnet Httpclient,Httpclientfactory,以下两种设置HttpClient的场景之间是否存在差异 我应该选择一个而不是另一个吗 类型化客户端: public class CatalogService { private readonly HttpClient _httpClient; public CatalogService(HttpClient httpClient) { _httpClient = httpClient; } public async Task&

以下两种设置HttpClient的场景之间是否存在差异

我应该选择一个而不是另一个吗

类型化客户端:

public class CatalogService 
{
    private readonly HttpClient _httpClient;
    
    public CatalogService(HttpClient httpClient) {
        _httpClient = httpClient;
    }
    
    public async Task<string> Get() {
        var response = await _httpClient.GetAsync();
        ....
    }
    
    public async Task Post() {
        var response = await _httpClient.PostAsync();
        ...
    }
}
// Startup.cs
//Add http client services at ConfigureServices(IServiceCollection services)
services.AddHttpClient<ICatalogService, CatalogService>();
公共类目录服务
{
私有只读HttpClientu HttpClient;
公共目录服务(HttpClient HttpClient){
_httpClient=httpClient;
}
公共异步任务Get(){
var response=await_httpClient.GetAsync();
....
}
公共异步任务Post(){
var response=wait_httpClient.PostAsync();
...
}
}
//Startup.cs
//在ConfigureServices(IServiceCollection服务)中添加http客户端服务
services.AddHttpClient();
IHttpClientFactory:

public class CatalogService 
{
    private readonly IHttpClientFactory _factory;
    
    public CatalogService(IHttpClientFactory factory) {
        _factory = factory;
    }
    
    public async Task<string> Get() {
        var response = await _factory.CreateClient().GetAsync();
        ....
    }
    
    public async Task Post() {
        var response = await _factory.CreateClient().PostAsync();
        ...
    }
}
// Startup.cs
//Add http client services at ConfigureServices(IServiceCollection services)
services.AddHttpClient();
```
公共类目录服务
{
私有只读IHttpClientFactory\u工厂;
公共目录服务(IHttpClientFactory工厂){
_工厂=工厂;
}
公共异步任务Get(){
var response=await_factory.CreateClient().GetAsync();
....
}
公共异步任务Post(){
var response=await_factory.CreateClient().PostAsync();
...
}
}
//Startup.cs
//在ConfigureServices(IServiceCollection服务)中添加http客户端服务
services.AddHttpClient();
```
具有抽象性(即
IHttpClient
)要好得多,也更受社区的赞扬。它允许您分配
HttpClient
以及自定义编写的
IHttpClient
,而无需更改
CatalogService

在创建大型系统时,这是非常关键的一点,因为您对具体实现的依赖性降低了,维护成本也降低了

此外,使用抽象可以显示实际的用途,并减少可能的干扰。一个例子:

public interface MyInterface
{
    void UsefulMethod();
}

public class MyClass : MyInterface
{
    public float variable1;
    public float moreBurden;
    public float thisIsNotRequiredAtAll;

    public void UsefulMethod() {}
    public void AnotherMethod() {}
    public void MoreNoiseMethod() {}
}

public class MyService
{
    private MyClass _myClass;

    public MyService(MyClass myClass)
    {
        _myClass = myClass;
    }

    public void MyOnlyMethod()
    {
        _myClass.UsefulMethod();
    }
}
在这种情况下,您只使用一种方法,但您的服务可以访问大量不必要的信息,从而分散了目标的注意力。要创建
MyService
,其创建者必须能够创建
MyClass
的实例

现在image
MyService
的编写方式如下

public class MyService
{
    private IMyInterface _myInterface;

    public MyService(IMyInterface myInterface)
    {
        _myInterface = myInterface;
    }
   
    public void MyOnlyMethod()
    {
        _myInterface.UsefulMethod();
    }
}

现在,
\u myInterface
的目的很清楚了-您只需要一个特定的方法子集
MyService
只能访问该单一方法,并且不会被所有可能的实现细节分散注意力。

在我看来,我将继续传递
HttpClient
。原因是,

  • KISS原则-CatalogService
  • 真正需要的是一个
    HttpClient
    。该服务不关心如何获得客户机
  • 单一责任原则(SRP)-假设明天您必须保留两个
    CatalogService
    实例,以便向两个不同的端点发送请求,
    • 您可以传入
      IHttpClientFactory
      并在
      CatalogService
      内部实现路由,但这会破坏SRP
    • 或者,您可以创建
      目录服务工厂
      。该工厂获得传入的
      IHttpClientFactory
      ,并在内部实现路由。这也被称为关注点分离

  • 我认为,当你从消费的角度来看它们时,最大的区别就显现出来了

    类型化客户端 您将收到一个
    HttpClient
    实例,该实例可能已使用一些针对瞬时故障的弹性策略和一些默认值进行了修饰。您甚至可能会收到一个已经设置了
    BaseUrl
    的客户端

    因此,如果需要将RESTAPI客户机隐藏在强类型服务层后面,这种方法可能特别有用

    命名客户 当您需要来自特定客户机的多个实例或需要多个不同的客户机时,此技术会大放异彩。如果您注册了多个具有不同名称的不同客户端,那么您可以通过单个API轻松检索它们

    因此,如果您需要调用不同的下游系统,并且需要聚合它们的结果,那么这种方法可能很有用

    好读的文章

    这是否回答了您的问题@朱利安,不,因为它是关于旧的HTTPFactory虽然这一切可能都是真的,但我的直觉是你错过了ops问题的重点是,我错了,我错过了
    IHttpClientFactory
    而不是
    IHttpClient
    。。。