1 / 35

Dependency Injection & Inversion Of Control

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#

ross
Télécharger la présentation

Dependency Injection & Inversion Of Control

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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 intwindowCount; public Car() { this.engine = new Engine(); this.registration = "SW14ABC"; this.windowCount = 6; } } public class Car { private Engine engine; private String registration; private intwindowCount; 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 ElectricEngineengine; public ElectricCar(ElectricEngineengine) { this.engine = engine; } } public class DieselCar { private DieselEngineengine; public DieselCar(DieselEngineengine) { this.engine = engine; } }

  18. Interfaces public class Car { private IEngineengine; public Car(IEngineengine) { 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 IEngineengine; public Car(IEngineengine) { 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. Inversion of Control 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<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.

  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( IWindsorContainercontainer, IConfigurationStorestore) { 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…

  33. Installers public void Install( IWindsorContainercontainer, 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

More Related