Ok, so I think that I have a basic understanding of IoC and the patterns relating to it, dependency injection and the service locator pattern. From what I have read it seems that dependency injection into a class constructor is more favourable for loose coupling that the service locator. What I am having trouble understanding, and can’t really find anything written about it, is what to do if I want to instantiate an object from a high level class? Do I have the change the constructor for the class which is calling the new class? If so, that would mean that I would have to change the every call to that constructor and the constructors of every class making that call, and so to the root. This seems very cumbersome and unsafe. Would a service locator be more appropriate in this scenario? Any advice would be appreciated.
Simple example:
class car
void car(iBrand brand, iModel model){
_brand=brand;
_model=model;
}
class brand : iBrand
void brand (iModel model){
_model=model;
}
class model : iModel
void model()
This is a particularly crude example but hopefully should get my point across. each of these objects instantiates the class below. Now if I want to create an iEngine in the model class, does this mean it has to be passed all the way down from the top, including into the car constructor?
class car
void car(iBrand brand, iModel model, iEngine engine){
_brand=brand;
_model=model;
_engine=engine;
}
Thanks, H
-
Can you illustrate your question with an example?Steven– Steven2014年02月04日 09:08:18 +00:00Commented Feb 4, 2014 at 9:08
-
hope that example is enough. Thanks Steven.Eds– Eds2014年02月04日 09:34:23 +00:00Commented Feb 4, 2014 at 9:34
1 Answer 1
There should be only one place in your application that is instantiating injectable classes; the Composition Root. So there should be nobody but the Composition Root who is calling the components' constructors. It should be the Composition Root who composes the object graphs.
A dependency should only be included in the constructor of a type, if that type uses that dependency directly. In your example both Brand and Car depend on IModel, but if Car doesn't need to interact with IModel directly, model should not be injected into Car. Or imagine a UsersController class that depends on an IUserRepository. If the UserRepository needs to be extended with some logging, the UsersController should not have to know about this. You should just inject an ILogger into the UserRepository's constructor and the UsersController stays unaffected.
Since the Composition Root is the only place that calls the constructor, and adding dependencies should not ripple through the whole dependency graph, changing a constructor should mean that only the Composition Root is affected (besides the class in question of course). And if you use a DI framework, you will in most cases even prevent having to change anything at all.
2 Comments
Explore related questions
See similar questions with these tags.