|
|
Dependency Injection / Inversion of Control (IoC) Containers
There’s one final topic which is appropriate to discuss when describing dependency injection: IoC containers. (Dependency injection is also known as “Inversion of Control,” as originally described by Robert Martin. Interestingly enough, the development community typically uses the phrase “dependency injection” when talking about the technique itself and “IoC” when talking about dependency injection containers. But rest assured, there is no difference whatsoever between “Dependency Injection” and “Inversion of Control (IoC).”) An IoC Container is a utility which is leveraged to initialize and inject dependencies into the objects that use them. While it is a bit more difficult to visualize than the “manual” dependency injection we performed in the previous refactoring step, an IoC Container is nothing more than an object factory which initializes an object and satisfies its service dependencies in the process.
With most IoC Containers (e.g., Ninject, Castle Windsor, LinFu, and many others), there are only a couple of steps required to setup and use the IoC Container:
1. Register all of the classes which may be injected into another object. In our carefree efforts for world domination via our robot, this would include, at minimum, registering the service classes MobilePlatform and StereoCamera. While each IoC Container has its own means of registering a class for later retrieval, the underlying mechanism is often as simple as adding the service class’ object type to a hashtable for later lookup. If we were using Castle Windsor with our project, the registration lines would look like the following:
view plaincopy to clipboardprint?
1. container.AddComponent("camera",
2. typeof(IStereoCamera), typeof(StereoCamera));
3. container.AddComponent("mobilePlatform",
4. typeof(IMobilePlatform), typeof(MobilePlatform));
5. container.AddComponent("camera", typeof(WorldDomination));
container.AddComponent("camera",
typeof(IStereoCamera), typeof(StereoCamera));
container.AddComponent("mobilePlatform",
typeof(IMobilePlatform), typeof(MobilePlatform));
container.AddComponent("camera", typeof(WorldDomination));
Note that the last line registers the WorldDomination class itself. In doing so, we can let the IoC Container take care of the work of instantiating it with its service dependencies already injected. We don’t have to hand off instantiation of this class to the IoC Container, but it provides a useful benefit. Suppose the WorldDomination class needs a third service dependency provided via its constructor somewhere down the road. If we aren’t using an IoC Container to manage its creation, we’d have to look for every place where the class is created, via the new keyword, and pass in the extra dependency. If we leave its creation to the IoC Container, then we simply add the new service interface parameter to its constructor and the IoC Container will take care of the rest, assuming you’ve registered the third dependency as well. |
|