C# – Is it worth allowing HttpClient injection in the library

c

I'm making a library for other developers to use and it's for communicating with a 3rd party web service. I read the issue that come up around HttpClient and I would like to handle this properly, so that the library doesn't become a burden.

I thought I would make a base ServiceClient that would have 3 ways to construct it.

The first would instantiate the HttpClient itself via using a static Lazy<HttpClient> to keep a single instance in the lib. If this constructor is never used, the inner object never gets instantiated.

The second constructor would accept an HttpMessageHandler and instantiate the HttpClient with it every time. This would be sort of a unit test-friendly mocking constructor that wouldn't get much use otherwise.

The third constructor would accept an HttpClient instance, making the developer responsible for the lifetime of the object if that is their wish.

My initial thought was that a developer might be already using an HttpClient in their code and they could pass that same instance to the lib and prevent having more than one instance. But then I thought the client and the lib would be communicating with totally different endpoints and the lib's configuration (base url, headers, etc) would conflict with the calling code, which is not useful for anyone.

So now I'm leaning towards dropping the 3rd constructor, because I'm not sure if it brings anything to the table.

Does anyone have experience with this?

Best Answer

HttpClient isn't really designed to be replaced with an alternative (it doesn't have a series of abstract interfaces which are generic).

So I doubt there are any API-compliant HttpClient replacements. That makes it a quite poor candidate for the kind of abstraction you are talking about.

The reasons which MIGHT make sense in your application is because there maybe some upstream requirements for communication which require either parameters to be passed in or otherwise specified. For example, you might need to specify a username/password, and client side cert, or set other parameters. It is for THIS reason, primarily, that allowing an optional CTOR argument of type HttpClient probably makes sense.

If you elect to provide an optional HttpClient parameter to the constructor, I would NOT define it so that the caller controls its lifetime. There would be no easy way to coordinate the assumptions about lifetime. Instead, consider it an ADOPTION, where your library ADOPTS ownership of the HttpClient passed in.