Dependency Injection & Inversion Of Control
description
Transcript of Dependency Injection & Inversion Of Control
![Page 1: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/1.jpg)
DEPENDENCY INJECTION &
INVERSION OF CONTROL
![Page 2: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/2.jpg)
WHAT’S GOING TO BE COVERED
• Quick intro to C# for Java developers
• Dependency Injection
• Inversion of Control
• Containers
• Castle Windsor
![Page 3: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/3.jpg)
C# FOR JAVA DEVELOPERS
• Most of this lecture is going to use C#
• DI is possible with any object-oriented language
• IoC requires a container
![Page 4: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/4.jpg)
C# FOR JAVA DEVELOPERS
Java C#public class Car{
private Engine engine;private string registration;private int windowCount;
public Car(){
this.engine = new Engine();this.registration = "SW14ABC";this.windowCount = 6;
}}
public class Car {private Engine engine;private String registration;private int windowCount;
public Car() {this.engine = new Engine();this.registration = "SW14ABC";this.windowCount = 6;
}}
![Page 5: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/5.jpg)
C# FOR JAVA DEVELOPERS
Java C#private Engine engine;private string registration;
public Engine Engine{
get{
return this.engine;}set{
this.engine = value;}
}
public String Registration{
get{
return this.registration;}
}
private Engine engine;private String registration;
public Engine getEngine() {return this.engine;
}
public void setEngine(Engine engine) {this.engine = engine;
}
public String getRegistration() {return this.registration;
}
![Page 6: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/6.jpg)
C# FOR JAVA DEVELOPERS
Java C#private string registration;
public Engine Engine { get; set; }
public String Registration{
get{
return this.registration;}
}
private Engine engine;private String registration;
public Engine getEngine() {return this.engine;
}
public void setEngine(Engine engine) {this.engine = engine;
}
public String getRegistration() {return this.registration;
}
![Page 7: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/7.jpg)
C# FOR JAVA DEVELOPERS
Java C#public Engine Engine { get; set; }
public String Registration { get; private set; }
private Engine engine;private String registration;
public Engine getEngine() {return this.engine;
}
public void setEngine(Engine engine) {this.engine = engine;
}
public String getRegistration() {return this.registration;
}
![Page 8: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/8.jpg)
C# FOR JAVA DEVELOPERS
Java C#using System;
namespace DITest{ public class Engine { public void GoFaster() { Console.WriteLine("VROOM!!"); } }}
import java.lang.*;
package com.stwalkerster.uni.masterclass;
public class Engine {public void goFaster() {
System.out.println("VROOM!!");}
}
![Page 9: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/9.jpg)
DEPENDENCY INJECTION
![Page 10: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/10.jpg)
”
“"Dependency Injection" is a 25-dollar term for a 5-cent concept.
James Shore - http://www.jamesshore.com/Blog/Dependency-Injection-Demystified.html
![Page 11: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/11.jpg)
LET’S LOOK AT AN EXAMPLE…
public class Car{
private Engine engine;
public Car(){
this.engine = new Engine();}
}
• The car makes a new engine when the car is being constructed
![Page 12: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/12.jpg)
DEPENDENCY INJECTION IS GIVING AN OBJECT IT’S DEPENDENCIES.
That’s pretty much all there is to it!
![Page 13: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/13.jpg)
LET’S LOOK AT AN EXAMPLE…
public class Car{
private Engine engine;
public Car(){
this.engine = new Engine();}
}
• We move the creation of the dependency into whatever creates the object in the first place
![Page 14: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/14.jpg)
LET’S LOOK AT AN EXAMPLE…
public class Car{
private Engine engine;
public Car(Engine engine){
this.engine = engine;}
}
• We move the creation of the dependency into whatever creates the object in the first place
• The created engine is now slotted into the car when the car is being constructed
![Page 15: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/15.jpg)
BUT WHY?
• Better separation of code
• Better testability through stubs and mock objects
• The object doesn’t need to know implementation details of it’s dependency.
![Page 16: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/16.jpg)
HIDING THE IMPLEMENTATION DETAILS
public class Car{
private Engine engine;
public Car(Engine engine){
this.engine = engine;}
}
• At the moment, our class depends on an instance of an Engine
• This Engine class is fully functioning
• This could be something like a database connection.
• But what if we wanted to swap this for an ElectricEngine? What about a DieselEngine?
![Page 17: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/17.jpg)
public class ElectricCar{
private ElectricEngine engine;
public ElectricCar(ElectricEngine engine){
this.engine = engine;}
}
public class DieselCar{
private DieselEngine engine;
public DieselCar(DieselEngine engine){
this.engine = engine;}
}
![Page 18: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/18.jpg)
INTERFACES
public class Car{
private IEngine engine;
public Car(IEngine engine){
this.engine = engine;}
}
• Now our class doesn’t care what sort of engine it gets, as long as it looks like and behaves like an engine, it’s good enough.
• As our IEngine interface exposes everything we need to access on the engine, we can continue as normal
![Page 19: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/19.jpg)
INTERFACES
public class Car : ICar{
private IEngine engine;
public Car(IEngine engine){
this.engine = engine;}
}
• Now our class doesn’t care what sort of engine it gets, as long as it looks like and behaves like an engine, it’s good enough.
• As our IEngine interface exposes everything we need to access on the engine, we can continue as normal
![Page 20: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/20.jpg)
UNIT TESTINGpublic class Car{
public Car(IEngine engine){this.Engine = engine;}
public IEngine Engine { get; set; }
public void Drive(){this.Engine.GoFaster();}
}
• If we want to test our Car class, we need an IEngine
• Unit testing is supposed to be of a small unit of code
• We can’t unit test the Drive() method…
… unless we have an engine which has no side effects!
• We use a mock or a stubbed-out implementation of the engine which does nothing.
• We simply pass this mock in with DI
![Page 21: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/21.jpg)
UNIT TESTINGpublic class Car{
public Car(IEngine engine){this.Engine = engine;}
public IEngine Engine { get; set; }
public void Drive(){this.Engine.GoFaster();}
}
[Test]public void TestDriveCar(){
IEngine engine = new MockEngine();
Car myCar = new Car(engine);
// Check the Drive method does the// correct thing…
myCar.Drive()}
![Page 22: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/22.jpg)
A QUICK NOTE…
• Dependencies don’t have to be injected through the constructor.
• It’s acceptable to pass in dependencies through properties or getter/setter methods too
![Page 23: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/23.jpg)
INVERSION OF CONTROL
![Page 24: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/24.jpg)
INVERSION OF CONTROLpublic class Application
{
public static void Main(string[] args)
{
IEngine engine = new ElectricEngine();
Car car = new Car(engine);
car.Drive();
}
}
• Dependency Injection removes the need for building dependencies from the class which depends on them
• The problem is just shifted to the caller.
• We need to know the concrete implementation of the Engine at compile time
![Page 25: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/25.jpg)
INVERSION OF CONTROLpublic class Application
{
public static void Main(string[] args)
{
IEngine engine = new ElectricEngine();
Car car = new Car(engine);
car.Drive();
}
}
• With Inversion of Control, we delegate the management of the entire lifecycle of the objects to a container.
![Page 26: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/26.jpg)
INVERSION OF CONTROL
• The Inversion of Control framework (or container) is aware of the programmer’s code, and makes calls to it.
• This is the opposite of an API (which the developer calls). Hence “Inversion”
![Page 27: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/27.jpg)
IOC CONTAINERS
• Castle Windsor (.NET)
• Spring (Java)
• Guice ( Java)
• Autofac (.NET)
• Ninject (.NET) Prism (.NET)
• StructureMap (.NET)
![Page 28: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/28.jpg)
THREE CALLS
• The container is used in three different stages• Bootstrapping
• Resolving
• Disposing
![Page 29: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/29.jpg)
BOOTSTRAPPING
IWindsorContainer container =
new WindsorContainer()
.Install( FromAssembly.This() );
• Set up the IoC container, including:• Creation of the container
• Configuration of the container
• Register all the components that are needed
![Page 30: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/30.jpg)
RESOLVING
IApplication app =
container.Resolve<IApplication>();
• Get an instance of the root component of the application.
• This should be called as few times as possible – the vast majority of applications will have a single root component.
![Page 31: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/31.jpg)
DISPOSING
container.Dispose();
• Often forgotten
• Shutting down the container will shutdown all the components it manages
• Remember the container manages the entire life cycle of components.
![Page 32: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/32.jpg)
INSTALLERS
public void Install(IWindsorContainer container, IConfigurationStore store)
{container.Register(
Component.For<IEngine>()
.ImplementedBy<Engine>());
}
• Castle Windsor requires the use of an object which extends from IWindsorInstaller to register all of it’s components
• Registration can be split amongst WindsorInstallers
• During the bootstrapping phase, FromAssembly.This() loads all the installers into Castle Windsor
• Registration can be done one component at a time…
![Page 33: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/33.jpg)
INSTALLERS
public void Install(IWindsorContainer container, IConfigurationStore store)
{container.Register(
Classes.FromThisAssembly().InNamespace(“DITest").WithService.AllInterfaces()
);}
• … or by convention.
• Registering by convention is preferred, as there is much less configuration to do.
• Castle also supports registering via XML files, which allows you to swap out classes at runtime, rather than at compile-time.
![Page 34: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/34.jpg)
DEBUGGING
• Clicking “View Detail…” will show more information about what caused an exception
![Page 35: Dependency Injection & Inversion Of Control](https://reader035.fdocuments.in/reader035/viewer/2022062310/568163f4550346895dd57f09/html5/thumbnails/35.jpg)
IN THE LAB…
• You will be implementing a basic application to drive a car.
• The car needs an engine, and the application needs the car.
• Use Castle Windsor to create the instances