Dependency injection with unity 2.0 Dmytro Mindra Lohika

Post on 25-May-2015

1.880 views 1 download

description

Dependency injection with unity 2.0 Dmytro Mindra Lohika

Transcript of Dependency injection with unity 2.0 Dmytro Mindra Lohika

Dependency Injection with Unity 2.0

Dmytro MindraRnD Tech Lead

Lohika

Вторая встреча Microsoft .Net User Group Одесса, 2010

Goal

• Get DI understanding• Get Unity 2.0 understanding• Learn how to add Unity 2.0 to your projects

Plan

• Inversion of Control principle (IoC)• Dependency Injection pattern (DI)• Unity 2.0• Live Demo

Problem

Problem

We live in an age where writing software to a given set of requirements is no longer enough.

We have to maintain and change existing code.

How?

Our solutions should be:• Modular• Testable• Adaptive to change

Terms

• Service —An object that performs a well-defined function when called upon

• Client —Any consumer of a service; an object that calls upon a service to perform a well-understood function

Terms

• Dependency —A specific service that is required by another object to fulfill its function.

• Dependent —A client object that needs a dependency (or dependencies) in order to perform its function.

PRE DI APPROACHES

Ex1:Composition

Ex1:Composition public class SpellCheckerService{}

public class TextEditor

{ private SpellCheckerService _spellCheckerService; public TextEditor() { _spellCheckerService = new SpellCheckerService(); } } class Program { static void Main(string[] args) { TextEditor textEditor = new TextEditor(); } }

TextEditor

SpellChecker

What’s good

• It’s simple

What’s bad

• It’s not testable• It’s hard to maintain/change

Ex2: Factory

Ex2: Factory

public interface ISpellCheckerService { string CheckSpelling(); }

Ex2: Factory

public class SpellCheckerService: ISpellCheckerService

{ public string CheckSpelling()

{ return “Real”; } }

Ex2: Factory public class SpellCheckerFactory { private static ISpellCheckerService

_spellCheckerService = new SpellCheckerService();

public static ISpellCheckerService SpellCheckerService

{ get{ return _spellCheckerService; } set{ _spellCheckerService = value; } } }

Ex2: Factorypublic class TextEditor{ private ISpellCheckerService _spellCheckerService; public TextEditor() { _spellCheckerService =

SpellCheckerFactory.SpellCheckerService; }

public string CheckSpelling() { return _spellCheckerService.CheckSpelling(); }}

Ex2:Factory Unit Testingpublic class SpellCheckerServiceMock: ISpellCheckerService

{ public string CheckSpelling() { return “Mock”; } }

Ex2:Factory Unit Testing [TestFixture] class EmailerFactoryUnitTests { [Test] public void EmailerFactoryTest() {

ISpellCheckerService mockSpellCheckerService = new SpellCheckerServiceMock();

SpellCheckerFactory.SpellCheckerService = mockSpellCheckerService;

TextEditor textEditor = new TextEditor(); Assert.AreEqual(“Mock”,

textEditor.CheckSpelling()); } }

Ex2: Factory

SpellCheckerServ iceFactory

- SpellCheckerService: SpellCheckerService

TextEditor

+ CheckSpelling() : bool

SpellCheckerServ ice

+ CheckSpelling() : string

«interface»ISpellCheckerServ ice

+ CheckSpelling() : string

SpellCheckerServ iceMock

+ CheckSpelling() : string

getSpellCheckerService

What changed

• TextEditor is still looking for its dependencies by itself. But now we can plug in different services without letting him know.

What’s good

• It’s testable• It’s easier to maintain/change

What’s bad

• You have to maintain factory or service locator• Dependent is still looking for Dependencies by

himself.• Dependencies are encapsulated and are not

obvious.

Service Locator

Unfortunately, being a kind of Factory, Service Locators suffer from the same problemsof testability and shared state.

Inversion of Control

Common Flow• TextEditor creates its

dependency by himself.

IoC Flow• TextEditor requests factory

to create dependency for him.

SpellCheckerServ iceFactory

- SpellCheckerService: SpellCheckerService

TextEditor

+ CheckSpelling() : bool

TextEditor

SpellChecker

Inversion of Control

• Hollywood Principle:

Don’t call me, I’ll call you

Inversion of Control

• IoC – is a common characteristic of frameworks.

• Inversion of Control serves as a design guideline.

• According to Martin Fowler the etymology of the phrase dates back to 1988.

Two principles of IOC

• Main classes aggregating other classes should not depend on the direct implementation of the aggregated classes. Both the classes should depend on abstraction.

• Abstraction should not depend on details, details should depend on abstraction.

Inversion of Controlas a Design Guideline

• Without IoC • With IoC

TextEditor

SpellChecker

TextEditor

+ CheckSpelling() : bool

SpellCheckerServ ice

+ CheckSpelling() : string

«interface»ISpellCheckerServ ice

+ CheckSpelling() : string

Loose coupling

TIME TO INJECT !

Ex3:Dependency Injection public class TextEditor { private readonly ISpellCheckerService

_spellCheckerService;

public TextEditor(ISpellCheckerService spellCheckerService)

{ _spellCheckerService = spellCheckerService; }

public string CheckSpelling() { return _spellCheckerService.CheckSpelling(); }

}

Ex3: Unit Testing DI

• Almost same as for Ex2// Mock ISpellCheckerService mock = new SpellCheckerServiceMock();

// InstantiateTextEditor textEditor = new TextEditor(mock);

// CheckAssert.AreEqual(“Mock”, textEditor.CheckSpelling());

What changed

• TextEditor lost its “Sovereignty” and is not able to resolve dependencies by himself.

What’s good

• Dependencies are obvious.• Dependency resolution is not encapsulated.• Unit Testing got little bit easier• Architecture is much better

What’s bad

• We are resolving dependencies manually while creating instances of TextEditor.

Dependency Injection

SpellCheckerServ ice

+ CheckSpelling() : bool

TextEditor

+ CheckSpelling() : bool

«interface»ISpellCheckerServ ice

Dependency Injection

• DI is IoC• Inversion of Control is too generic a term• DI pattern – describes the approach used to

lookup a dependency. • Dependency resolution is moved to

Framework.

Ex4: Unity

Ex4: Unity

using Microsoft.Practices.Unity;

UnityContainer container = new UnityContainer();

container.RegisterType<ISpellCheckerService, SpellCheckingService>();

TextEditor textEditor = container.Resolve<TextEditor>();

What changed

• Unity container now resolves dependencies

What’s good

• Automated dependency resolution

Unity methods

• RegisterType• RegisterInstance• Resolve• BuildUp

Ex5: Unity Configuration <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> </configSections>

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <alias alias="ISpellCheckerService" type="Unity.Config.ISpellCheckerService, Unity.Config" /> <alias alias="SpellCheckingService" type="Unity.Config.SpellCheckingService, Unity.Config" /> <namespace name="Unity.Config" /> <assembly name="Unity.Config" />

<container> <register type="ISpellCheckerService" mapTo="SpellCheckingService" /> </container> </unity>

Ex5: Unity Configuration

using Microsoft.Practices.Unity;using Microsoft.Practices.Unity.Configuration;

UnityContainer container = new UnityContainer();container.LoadConfiguration();TextEditor textEditor = container.Resolve<TextEditor>();

Dependency tree

Ex6: Dependency treepublic interface IAdditionalDependency{}public class AdditionalDependency : IAdditionalDependency{}

public class SpellCheckingService: ISpellCheckerService {

public SpellCheckingService( IAdditionalDependency dependency){} }

Ex6: Dependency Tree

UnityContainer container = new UnityContainer();container.RegisterType<ISpellCheckerService,

SpellCheckingService>();container.RegisterType<IAdditionalDependency,

AdditionalDependency>();TextEditor textEditor = container.Resolve<TextEditor>();

Ex6: Dependency tree

SpellCheckerServ ice

+ CheckSpelling() : bool

TextEditor

+ CheckSpelling() : bool

«interface»ISpellCheckerServ ice

AdditionalDependency

+ CheckSpelling() : bool

«interface»IAditionalDependenct

Injection Types

• Constructor Injection• Setter injection• Method call injection

Ex7: Defining Injection Constructor

public class TextEditor { private readonly ISpellCheckerService _spellCheckerService;

[InjectionConstructor] public TextEditor(ISpellCheckerService spellCheckerService) { _spellCheckerService = spellCheckerService; }

public TextEditor(ISpellCheckerService spellCheckerService,string name) { _spellCheckerService = spellCheckerService; } }

Ex8: Property Injection public class TextEditor { public ISpellCheckerService SpellCheckerService {get; set;}

[Dependency] public ISpellCheckerService YetAnotherSpellcheckerService{get;set;} } UnityContainer container = new UnityContainer(); container.RegisterType<TextEditor>(new InjectionProperty("SpellCheckerService")); container.RegisterType<ISpellCheckerService, SpellCheckingService>(); TextEditor textEditor = container.Resolve<TextEditor>();

Ex9: Method call injection public class TextEditor { public ISpellCheckerService SpellcheckerService {get; set;}

[InjectionMethod] public void Initialize (ISpellCheckerService spellcheckerService) { _spellCheckerService = spellcheckerService; } }UnityContainer container = new UnityContainer();//container.RegisterType<TextEditor>(

new InjectionMethod("SpellcheckerService"));container.RegisterType<ISpellCheckerService, SpellCheckingService>();TextEditor textEditor = container.Resolve<TextEditor>();

Lifetime Managers

• TransientLifetimeManagerReturns a new instance of the requested type for each call. (default behavior)

• ContainerControlledLifetimeManagerImplements a singleton behavior for objects. The object is disposed of when you dispose of the container.

Lifetime Managers

• ExternallyControlledLifetimeManagerImplements a singleton behavior but the container doesn't hold a reference to object which will be disposed of when out of scope.

• HierarchicalifetimeManagerImplements a singleton behavior for objects. However, child containers don't share instances with parents.

Lifetime Managers

• PerResolveLifetimeManagerImplements a behavior similar to the transient lifetime manager except that instances are reused across build-ups of the object graph.

• PerThreadLifetimeManagerImplements a singleton behavior for objects but limited to the current thread.

Ex10: Unity Singleton

UnityContainer container = new UnityContainer();container.RegisterType<ISpellCheckerService, SpellCheckingService>(new ContainerControlledLifetimeManager());TextEditor textEditor = container.Resolve<TextEditor>();

Container Hierarchy

Unity Limitations

• When your objects and classes have no dependencies on other objects or classes.

• When your dependencies are very simple and do not require abstraction.

What Unity stands for

For• Wiring framework

components

Not for• Wiring small parts

Performance

Performance

Performance

.NET DI Frameworks

• Unity 2.0• AutoFac 2.3.2• StructureMap 2.6.1• Castle Windsor 2.1• Ninject 2.0

Additional reading

Additional reading

Live Demo

QUESTIONS ?

THANK YOU !