Dependency Injection Phil Pratt-Szeliga CSE 784 Fall 2010
Jan 21, 2016
Dependency Injection
Phil Pratt-SzeligaCSE 784Fall 2010
References
Dependency Injection
Design patterns using Spring and Guice
Dhanji R. Prasanna http://en.wikipedia.org/wiki/Dependency_injection
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; }
}
}
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?
Pre-DI Solutions
Construction by hand Factory Pattern
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());
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.
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
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; }
} }
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( );
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
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
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