Dependency Injection: Keeping It Simple
March 12, 2013 Leave a comment
When I gave my talk at TriNug’s SIG about the SOLID principles, I whipped up an example of Dependency Injection (DI) that some people really liked. I decided to blog about it. Consider a basic console application that has a single Interface included – Animal. The Animal interface looks like this:
public interface IAnimal { void Talk(); void Eat(); }
The Console application includes a couple of classes that implement the interface:
public class Elephant: IAnimal { public void Talk() { Console.WriteLine("Trumpet"); } public void Eat() { Console.WriteLine("Yummy Peanuts"); } } public class Seal(): IAnimal { public void Talk() { Console.WriteLine("Ark Ark"); } public void Eat() { Console.WriteLine("Yummy Fish"); } }
Then in the Main method, I want to inject in an animal at run time. I could write something like this:
static void Main(string[] args) { IAnimal animal = ????; animal.Talk(); animal.Eat(); }
What I don’t want to do is to have a switch/if..then statement in the Main function because as new animals are added to my project, I would have to update existing code and violate the Open/Closed principle. I know if a couple of ways around this problem:
- Using a Dependency Injection Framework like Unity
- Using Microsoft Extension Framework
- Use a Factory Pattern
- Injecting the name of the class and using Activator to resolve. Note that this name can come from a database call or a .config file.
A DI framework seems a bit too heavy for this kind of solution. I tried MEF and quickly gave up, Using a factory pattern delays but does not alter the problem resolution. I think the Activator keyword is the best solution to my problem.
To that end, I added a section in my .config file like this:
<configuration> <appSettings> <add key="animalTypeName" value="Tff.PoorMansDependencyInjection.Seal"/> </appSettings> </configuration>
And then in my Main method:
String animalTypeName = ConfigurationManager.AppSettings["animalTypeName"].ToString(); Type animalType = Type.GetType(animalTypeName); IAnimal animal = (IAnimal)Activator.CreateInstance(animalType); animal.Talk(); animal.Eat(); Console.ReadKey();
And I get this: