I have written a little bit of code which illustrates DI(dependency injection) and IoC(Inversion of control) container. The point of this exercise is to illustrate the two methods by which you can actieve inversion of control.
Please let me know if this code achieves the objective. (That is, if I have illustrated the two concepts clearly. Let me know if there is any improvement possible. (In any area like coding style, naming style, comments)
I have 4 classes for this:
Dependencies
: This class holds the interface and the two concrete implementationsCoreClassDI
: This class illustrates dependency injectionControlInversionAid
: This holds a simple IoC container following instructions from here. Hence I will not be sharing this code for review.Program
: This is the console application that illustrates the conceptsWritePredictions
: This invokes the method on the dependency
Now, for the code:
Dependencies
namespace Dependencies
{
public interface IPredictingFuture
{
string WhatWillBeGoodNextYear();
}
public class EartAndSkyPrediction : IPredictingFuture
{
public EartAndSkyPrediction()
{
Console.ForegroundColor = ConsoleColor.DarkGreen;
}
public string WhatWillBeGoodNextYear()
{
return ("Everything will be good next year, especially if you are good!");
}
}
public class BadConnections : IPredictingFuture
{
public BadConnections()
{
Console.ForegroundColor = ConsoleColor.Red;
}
public string WhatWillBeGoodNextYear()
{
return ("Take care!! It is a terrible year :-(");
}
}
}
CoreClassDI
namespace CoreClassDI
{
public class TheOracle
{
//Property Injection. This is injecting the correct concrete implementation
//through a property. One can also use a constructor or an
//interface implementation to inject dependencies.
public IPredictingFuture FuturePredictions { get; private set; }
//This is a predict function in which you "inject" the concrete class
//in the property. The property injection is achieved through the constructor.
//We can also alternatively inject dependencies through the WriteOutPredictions()
//function.
public TheOracle(IPredictingFuture predictionType)
{
FuturePredictions = predictionType;
}
}
}
WritePredictions
namespace ClientCode
{
//This is the class which actually writes out the predictions based on the
//actual class loaded either through Injection or the IoC container
public class WritePredictions
{
public static void WritePredictionsOnScreen(IPredictingFuture predictIt)
{
Console.WriteLine("How will my year be?");
Console.WriteLine(predictIt.WhatWillBeGoodNextYear());
Console.WriteLine("**********");
}
}
}
Program
namespace ClientCode
{
//This is the main program which controls and illustrates the different types of DI
//You need to start debug in one of these programs to understand the concepts
//of DI and IoC
class Program
{
static void Main(string[] args)
{
string choice;
string input;
Console.WriteLine("Choose the correct option");
Console.WriteLine("1 for dependency injection");
Console.WriteLine("2 for IoC container");
input = Console.ReadKey().KeyChar.ToString();
switch (input)
{
case "1":
Console.WriteLine("Welcome! Do you want a good prediction? Or a Bad prediction?");
Console.WriteLine("Hit G for good predictions and B for bad predictions");
choice = Console.ReadKey().KeyChar.ToString();
IPredictingFuture predictionObj = null;
//The dependency is loaded based on run time choice
switch (choice)
{
case "G":
case "g":
//Setting good predictions
predictionObj = new EartAndSkyPrediction();
break;
case "B":
case "b":
//Setting bad predictions on the same object
predictionObj = new BadConnections();
break;
default:
Console.WriteLine("Good going! Who cares anyway?");
break;
}
//Injecting the prediction object and calling the client code with it
TheOracle oracleObj = new TheOracle(predictionObj);
WritePredictions.WritePredictionsOnScreen(oracleObj.FuturePredictions);
Console.ReadKey(true);
break;
case "2":
Console.WriteLine("Welcome! Do you want a good prediction? Or a Bad prediction?");
Console.WriteLine("Hit G for good predictions and B for bad predictions");
choice = Console.ReadKey().KeyChar.ToString();
switch (choice)
{
case "G":
case "g":
//Registering the good predictions
IoC.Register<IPredictingFuture, EartAndSkyPrediction>();
break;
case "B":
case "b":
//Loading the bad predictions
IoC.Register<IPredictingFuture, BadConnections>();
break;
default:
Console.WriteLine("Good going! Who cares anyway?");
Console.ReadKey(true);
break;
}
//Resolving to the registered predictions
WritePredictions.WritePredictionsOnScreen(IoC.Resolve<IPredictingFuture>());
Console.ReadKey(true);
break;
default:
Console.WriteLine("Invalid choice");
Console.ReadKey(true);
break;
}
}
}
}