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.