13
Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Embed Size (px)

Citation preview

Page 1: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Dependency Injection

Phil Pratt-SzeligaCSE 784Fall 2010

Page 2: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

References

Dependency Injection

Design patterns using Spring and Guice

Dhanji R. Prasanna http://en.wikipedia.org/wiki/Dependency_injection

Page 3: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Hardwired Dependenciespublic interface SpellChecker {

bool checkSpelling(Document doc);

}

public class EnglishSpellChecker : SpellChecker {

public bool checkSpelling(Document doc){ //check the spelling here }

}

public class Emailer {

private SpellChecker mSpellChecker;

private Document mDocument;

public Emailer( ){ mSpellChecker = new EnglishSpellChecker(); }

public bool send( ) {

if(mSpellChecker.checkSpelling(mDocument)) { return true; }

else { return false; }

}

}

Page 4: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Problems with Hardwired Dependencies

Development What if your application needs to suddenly support

Spanish spell checkers, etc Testing

How can you pass in a mock SpellChecker to test that checkSpelling has been called?

Page 5: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Pre-DI Solutions

Construction by hand Factory Pattern

Page 6: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Construction by Handpublic class Emailer {

private SpellChecker mSpellChecker;

private Document mDocument;

public Emailer(SpellChecker checker){

mSpellChecker = checker

}

public bool send( ) {

if(mSpellChecker.checkSpelling(mDocument)) { return true; }

else { return false; }

}

}

Emailer emailer1 = new Emailer(new EnglishSpellChecker());

Emailer emailer2 = new Emailer(new SpanishSpellChecker());

Page 7: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Construction by Hand

Advantages: Useful for small projects. Provides a powerful way of

separating assemblies in small projects Disadvantages

Clients may directly depend on English and Spanish spell checker.

Page 8: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Separating Assemblies The problem: A high precision metal melting

factory uses a C# program to control the furnace temperature. The control program is one assembly The recipe editor is another assembly that can run in

standalone mode but has dependencies on the control program

The control program has an Furnace class with a huge number of dependencies (~10,000 SLOC)

We want to isolate the RecipeEditor class from the Furnace class so the Metallurgist can use the RecipeEditor at his/her desk

Page 9: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Separating Assemblies The solutionnamespace Furnace {

public class Furnace {

public showRecipeEditor( ) { new RecipeEditor(new OnlineRecipeEditorToFurnaceBridge( )).show(); }

}

private class OnlineRecipeEditorToFurnaceBridge : RecipeEditorToFurnaceBridge {

public int getElapsedTime( ) { return Furnace.getElapsedTime(); }

} }

namespace RecipeEditor {

public interface RecipeEditorToFurnaceBridge ( ) { int getElapsedTime( ); }

private class OfflineRecipeEditorToFurnaceBridge : RecipeEditorToFurnaceBridge {

public int getElapsedTime( ) { return 0; }

}

public class RecipeEditor {

private RecipeEditorToFurnaceBridge mBridge;

public RecipeEditor( RecipeEditorToFurnaceBridge bridge) { mBridge = bridge; }

} }

Page 10: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Factory Pattern

public class EmailerFactory {

public Emailer newEnglishEmailer( ) {

return new Emailer(new EnglishSpellChecker);

}

public Emailer newSpanishEmailer( ) {

return new Emailer(new SpanishSpellChecker);

}

}

Emailer emailer = new EmailerFactory( ).newEnglishEmailer( );

Page 11: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Factory Pattern

Advantages The clients are completely isolated from

EnglishSpellChecker and SpanishSpellChecker Disadvantages

Testing with Mock objects is hard to get right With many dependencies there is a lot of boilerplate code

written manually When you want to change a common dependency you have to

change it many places

Page 12: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Dependency Injection (Spring.NET)

IApplicationContext ctx = ContextRegistry.GetContext();

Emailer english_emailer = (Emailer)ctx.GetObject("EnglishEmailer");

Emailer spanish_emailer = (Emailer)ctx.GetObject("SpanishEmailer");

Document english_document = new Document("hello world");

Document spanish_document = new Document("hola mundo");

english_emailer.send(english_document);

spanish_emailer.send(spanish_document);

- ContextRegistry is configured with App.config file

Page 13: Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010

Dependency Injection Scope

Singleton – For each context and identifier, GetObject returns the same object

Prototype – Each time GetObject is called for a specific identifier, a new object is returned