This question is a follow-up to the questions here: Illustrating DI and IoC concepts : Simple code requesting review
I have taken the very good review comments got and tweaked the code. These are the classes I define:
Dependencies: This namespace holds the interfaces and concrete implementations.CoreClassDI: This class is primarily used to illustrate dependency injection.IoC: This class defines 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 concepts
Please have a look at my code and feel free to give me your opinion on any aspect of coding. Ofcourse, with an emphasis to the IoC and DI concepts. I have used my own IoC container as opposed to readymade ones since I wanted to understand the working better.
Here is the code.
Depedencies namespace
namespace Dependencies
{
public interface IPredictingFuture
{
IWriter Writer { get; set; }
string NewYearPrediction();
}
public class BadConnections : IPredictingFuture
{
public BadConnections()
{
Console.ForegroundColor = ConsoleColor.Red;
}
public string NewYearPrediction()
{
return "Take care!! It is a terrible year :-(";
}
public IWriter Writer { get; set; }
}
public class EartAndSkyPrediction : IPredictingFuture
{
public EartAndSkyPrediction()
{
Console.ForegroundColor = ConsoleColor.DarkGreen;
}
public string NewYearPrediction()
{
return "Everything will be just great next year!";
}
public IWriter Writer { get; set; }
}
//This is the template for any class which intends to communicate
//the message of the predicting classes to the end user.
//The return type of this method is void since it handles the
//communication of the message as implemented by the derived classes.
public interface IWriter
{
//Write the message in a format requested by the user.
void WriteMessage(string question);
}
//This class delivers the message by writing it out on the console.
public class ConsoleWriter : IWriter
{
public void WriteMessage(string message)
{
Console.WriteLine(message);
}
}
}
CoreClassDI
namespace CoreClassDI
{
//This class illustrates the dependency injection through the constructor.
public class CoreClassDI
{
//This is a private property which will be initialized by the
//constructor
private IPredictingFuture FuturePredictions { get; 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.
//Writer is a property of IPredictingFuture. The concrete class for this is
//being injected through the constructor here.
public CoreClassDI(IPredictingFuture predictionType, IWriter writer)
{
FuturePredictions = predictionType;
predictionType.Writer = writer;
}
public void WritePredictions()
{
FuturePredictions.Writer.WriteMessage(FuturePredictions.NewYearPrediction());
}
}
}
ClientCode
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("Choose the type of predictions you want:");
Console.WriteLine("G or g : Good predictions");
Console.WriteLine("B or b : 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;
}
var consoleWriter = new ConsoleWriter();
//Injecting the prediction object, writer object and calling the client code with it
CoreClassDI.CoreClassDI oracleObj = new CoreClassDI.CoreClassDI(predictionObj, consoleWriter);
oracleObj.WritePredictions();
Console.ReadKey(true);
break;
case "2":
Console.WriteLine("Choose the type of predictions you want:");
Console.WriteLine("G or g : Good predictions");
Console.WriteLine("B or b : Bad predictions");
//Registering the concrete implementation for IWriter here
IoC.Register<IWriter, ConsoleWriter>();
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 the registered dependencies
IPredictingFuture objPredictions = IoC.Resolve<IPredictingFuture>();
objPredictions.Writer = IoC.Resolve<IWriter>();
//Writing the message
objPredictions.Writer.WriteMessage(objPredictions.NewYearPrediction());
Console.ReadKey(true);
break;
default:
//Handing the invalid choice
Console.WriteLine("Invalid choice");
Console.ReadKey(true);
break;
}
}
}
}