35
DEPENDENCY INJECTION & INVERSION OF CONTROL

Dependency Injection & Inversion Of Control

  • Upload
    ross

  • View
    63

  • Download
    0

Embed Size (px)

DESCRIPTION

Dependency Injection & Inversion Of Control. What’s Going to be covered. Quick intro to C# for Java developers Dependency Injection Inversion of Control Containers Castle Windsor. C# for Java developers. Most of this lecture is going to use C# - PowerPoint PPT Presentation

Citation preview

Page 1: Dependency Injection & Inversion Of Control

DEPENDENCY INJECTION &

INVERSION OF CONTROL

Page 2: Dependency Injection & Inversion Of Control

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

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

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

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

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

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

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

DEPENDENCY INJECTION

Page 10: Dependency Injection & Inversion Of Control

“"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

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

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

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

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

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

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

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

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

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

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

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

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

INVERSION OF CONTROL

Page 24: Dependency Injection & Inversion Of Control

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

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

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

IOC CONTAINERS

• Castle Windsor (.NET)

• Spring (Java)

• Guice ( Java)

• Autofac (.NET)

• Ninject (.NET) Prism (.NET)

• StructureMap (.NET)

Page 28: Dependency Injection & Inversion Of Control

THREE CALLS

• The container is used in three different stages• Bootstrapping

• Resolving

• Disposing

Page 29: Dependency Injection & Inversion Of Control

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

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

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

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

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

DEBUGGING

• Clicking “View Detail…” will show more information about what caused an exception

Page 35: Dependency Injection & Inversion Of Control

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