简体   繁体   中英

Managing multiple instances of HttpClient using Dependency Injection

I'm creating an instance of HttpClient for each distinct API that my web application is communicating to.

I want to use Dependency Injection with SimpleInjector to inject HttpClient to the business classes. For example, I have ITwitterBusiness and IInstagramBusiness , and both of them accept HttpClient in their constructor.

What is the best practice when it comes to registering multiple objects of the same type using Dependency Injection?

I'm pretty sure that part of the problem could be my design, but here are some ideas.

My first idea is to use delegate in the DI registration

container.Register<ITwitterBusiness>(() => new TwitterBusiness(httpClientTwitter));

Seems simple enough, but I don't know if this method has any bad side effects, for example by making SimpleInjector run slower or if I'm breaking some design pattern.

My second idea is to use Context based injection http://simpleinjector.readthedocs.io/en/latest/advanced.html#context-based-injection

I believe this will allow me to inject a certain HttpClient instance to a certain class. Still not exactly sure how this works.

I'm very curious if I could solve this purely by design. For example by creating dummy classes. I just haven't found any good examples, but If I understand it correctly then I could create dummy classes such as HttpClientTwitter that inherits HttpClient , and that way I can get rid of the ambiguous registration.

Thanks!

My first idea is to use delegate in the DI registration. Seems simple enough, but I don't know if this method has any bad side effects, for example by making SimpleInjector run slower or if I'm breaking some design pattern.

The use of auto-wiring (the opposite of registering a delegate) is advised in case the type has any application components that need to be wired. Auto-wiring simplifies registration and allows Simple Injector to analyse the object graph. Both seem to be of no concern in your case. The HttpClient is not an application component, but an infrastructure type. There seem to be no other dependencies, so registering a delegate doesn't pose any maintainability issues.

Delegate registration is slower compared to the use of auto-wiring, Simple Injector isn't able to optimize as much using delegates. It is however very, very unlikely that you notice any performance difference when doing this. This is not something you should worry about.

My second idea is to use Context based injection. I believe this will allow me to inject a certain HttpClient instance to a certain class. Still not exactly sure how this works.

You can make distinct registrations based on the context. For instance:

var httpClientTwitterRegistration = Lifestyle.Transient.CreateRegistration<HttpClient>(
    () => new HttpClient("https://twitter"),
    container);

container.RegisterConditional(typeof(HttpClient), httpClientTwitterRegistration,
    c => c.Consumer.ImplementationType == typeof(TwitterBusiness));

var httpClientInstagramRegistration = Lifestyle.Transient.CreateRegistration<HttpClient>(
    () => new HttpClient("https://instagram"),
    container);

container.RegisterConditional(typeof(HttpClient), httpClientInstagramRegistration,
    c => c.Consumer.ImplementationType == typeof(InstagramBusiness));

I'm very curious if I could solve this purely by design

By injecting an HttpClient into the TwitterBusiness class you get the false sense of flexibility. You seem to be able two swap implementations, but since HttpClient is a concrete type, changing implementations makes no sense. Since TwitterBusiness communicates directly with HttpClient , this should be made an implementation detail. In other words, move the creation of HttpClient inside TwitterBusiness . Any arguments that you need to configure (an url perhaps) can be injected into TwitterBusiness . This way TwitterBusiness is in complete control over the creation and disposal of the HttpClient and you inject the only thing that is only interesting to change (the url).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM