4

下面2个设置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>();

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();
```
4

3 回答 3

2

我认为,从消费的角度来看,最大的区别就显现出来了。

打字客户端

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

因此,如果您需要将 REST API 客户端隐藏在强类型服务层之后,这种方法会特别有用。

命名客户

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

因此,如果您需要调用不同的下游系统并且需要汇总它们的结果,这种方法可能会很有用。

好读的文章

于 2020-10-12T07:46:06.783 回答
2

IMO,我会随波逐流HttpClient。原因是,

  1. KISS 原则-CatalogService真正需要的是一个HttpClient. 该服务不关心如何获得客户。
  2. 单一职责原则 (SRP) - 假设明天您必须保留两个实例CatalogService以将请求发送到两个不同的端点,
    • 您可以传入 aIHttpClientFactory并在内部实现路由CatalogService,但这会破坏 SRP。
    • 或者,您可以创建一个CatalogServiceFactory. 该工厂被IHttpClientFactory传入并在内部实现路由。这也称为关注点分离
于 2020-10-10T03:14:06.177 回答
-1

具有抽象性(即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

现在图像MyService写成

public class MyService
{
    private IMyInterface _myInterface;

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

现在,目的_myInterface很明确了——你只需要一个特定的方法子集。MyService只能访问该单一方法,并且不会被所有可能的实现细节分散注意力。

于 2020-10-09T19:41:40.733 回答