พิมพ์ HttpClient กับ IHttpClientFactory

มีความแตกต่างระหว่าง 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();
```

person Ivan Studenikin    schedule 09.10.2020    source แหล่งที่มา
comment
สิ่งนี้ตอบคำถามของคุณหรือไม่? HttpClientFactory.Create เทียบกับ HttpClient ใหม่   -  person Julian    schedule 09.10.2020
comment
@Julian ไม่เพราะมันเกี่ยวกับ HttpFactory เก่า   -  person Ivan Studenikin    schedule 13.10.2020


คำตอบ (3)


IMO ฉันจะผ่าน HttpClient เหตุผลก็คือ

  1. หลักการจูบ - สิ่งที่ CatalogService ต้องการจริงๆ คือ HttpClient บริการไม่สนใจเกี่ยวกับวิธีการรับลูกค้า
  2. Single Responsibility Principle (SRP) - Say tomorrow you have to keep two instances of CatalogService to send requests to two different endpoints,
    • You can pass in a IHttpClientFactory and implement routing inside CatalogService, but that breaks SRP.
    • หรือคุณสามารถสร้าง CatalogServiceFactory โรงงานนั้นได้รับการส่งผ่าน IHttpClientFactory และใช้การกำหนดเส้นทางภายใน เรียกอีกอย่างว่า การแยกข้อกังวล
person Han Zhao    schedule 10.10.2020

ฉันคิดว่าความแตกต่างที่ยิ่งใหญ่ที่สุดจะเผยให้เห็นเมื่อคุณมองจากมุมมองของการบริโภค

ลูกค้าที่พิมพ์

คุณจะได้รับ HttpClient อินสแตนซ์ ซึ่งอาจได้รับการตกแต่งด้วยกลยุทธ์ที่ยืดหยุ่นเพื่อรับมือกับความล้มเหลวชั่วคราวและด้วยค่าเริ่มต้นบางอย่าง คุณอาจได้รับไคลเอนต์ที่ตั้งค่า BaseUrl ไว้แล้ว

ดังนั้นแนวทางนี้จะมีประโยชน์อย่างยิ่งหากคุณต้องการซ่อนไคลเอ็นต์ REST API ไว้ด้านหลังชั้นบริการที่พิมพ์อย่างยิ่ง

ชื่อลูกค้า

เทคนิคนี้สามารถโดดเด่นได้เมื่อคุณต้องการหลายอินสแตนซ์จากไคลเอนต์เฉพาะ หรือเมื่อคุณต้องการไคลเอนต์ที่แตกต่างกันหลายตัว หากคุณได้ลงทะเบียนไคลเอนต์ที่แตกต่างกันหลายตัวด้วยชื่อที่แตกต่างกัน คุณสามารถเรียกข้อมูลลูกค้าเหล่านั้นได้อย่างง่ายดายผ่าน API เดียว

ดังนั้นแนวทางนี้อาจมีประโยชน์หากคุณต้องการเรียกใช้ระบบดาวน์สตรีมต่างๆ และคุณจำเป็นต้องรวมผลลัพธ์เข้าด้วยกัน

ดีที่จะอ่านบทความ

person Peter Csala    schedule 12.10.2020

การมีนามธรรม (เช่น 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 มีสิทธิ์เข้าถึงเพียงวิธีเดียวเท่านั้น และไม่ถูกรบกวนด้วยรายละเอียดการใช้งานที่เป็นไปได้ทั้งหมด

person tsvedas    schedule 09.10.2020
comment
แม้ว่าทั้งหมดนี้อาจเป็นเรื่องจริง แต่ความรู้สึกของฉันคือคุณพลาดประเด็นของคำถามปฏิบัติการ - person TheGeneral; 10.10.2020
comment
ใช่ ฉันผิดเอง ฉันพลาดไป IHttpClientFactory ไม่ใช่ IHttpClient... - person tsvedas; 10.10.2020