Download presentation
Presentation is loading. Please wait.
Published byDayna O’Connor’ Modified over 9 years ago
1
DEPENDENCY INJECTION & INVERSION OF CONTROL
2
WHAT’S GOING TO BE COVERED Quick intro to C# for Java developers Dependency Injection Inversion of Control Containers Castle Windsor
3
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
4
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; }
5
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; }
6
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; }
7
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; }
8
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!!"); }
9
DEPENDENCY INJECTION
10
” “ "Dependency Injection" is a 25-dollar term for a 5- cent concept. James Shore - http://www.jamesshore.com/Blog/Dependency-Injection-Demystified.html
11
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
12
DEPENDENCY INJECTION IS GIVING AN OBJECT IT’S DEPENDENCIES. That’s pretty much all there is to it!
13
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
14
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
15
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.
16
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?
17
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; }
18
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
19
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
20
UNIT TESTING public 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
21
UNIT TESTING public 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() }
22
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
23
INVERSION OF CONTROL
24
public 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
25
INVERSION OF CONTROL public 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.
26
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”
27
IOC CONTAINERS Castle Windsor (.NET) Spring (Java) Guice ( Java) Autofac (.NET) Ninject (.NET) Prism (.NET) StructureMap (.NET)
28
THREE CALLS The container is used in three different stages Bootstrapping Resolving Disposing
29
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
30
RESOLVING IApplication app = container.Resolve (); 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.
31
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.
32
INSTALLERS public void Install( IWindsorContainer container, IConfigurationStore store) { container.Register( Component.For ().ImplementedBy () ); } 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…
33
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.
34
DEBUGGING Clicking “View Detail…” will show more information about what caused an exception
35
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
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.