Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

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:

  1. Dependencies: This namespace holds the interfaces and concrete implementations.
  2. CoreClassDI: This class is primarily used to illustrate dependency injection.
  3. IoC: This class defines a simple IoC container following instructions from here. Hence I will not be sharing this code for review.
  4. 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;
            }
        }
    }
}
share|improve this question
add comment

1 Answer

up vote 1 down vote accepted

There are two issues I would like to emphasize in your question/code:

  1. it looks like you're trying to separate DI and IoC principles. In fact they are just different points of view on a same thing, because Dependency Injection is the software pattern usually used to implement Inversion of Control. So there is no need to make difference between them, quite often these terms are treated as synonyms, and most IoC containers do dependency injection as a part of their function.
  2. CoreClassDI knows too much about FuturePredictions, as it tries to initialize it with writer. This task should be delegated to IoC container (or the code that registers objects in container), and CoreClassDI should only use the pre-configured instance. Also, either IPredictingFuture should expose the method that predicts the future and outputs it to writer (so that CoreClassDI just calls this method) or IWriter should be declared on CoreClassDI class (preferably), and then this class acts as a mediator that gets prediction and outputs it to the writer. The line FuturePredictions.Writer.WriteMessage(FuturePredictions.NewYearPrediction()) highlights this problem
share|improve this answer
    
Thanks for your response! What I wanted to show was using a IoC container and DI directly side-by-side. And, then to explore which is more testable. This is why I am insisting on having saparate classes for both. IoC class for container. And CoreClassDI for direct dependency injection. Basically both these classes should be reflections of each other. They should not share responsibility. For, in the end, only one of them will survive! –  TheSilverBullet Dec 24 '12 at 11:59
1  
DI and IoC concepts are not competing. IoC is achieved via dependency injection, and IoC container is an implementation pattern that uses DI to wire up and initialize instances. –  almaz Dec 24 '12 at 12:09
    
As for your second point, you are right. FuturePredictions.Writer.WriteMessage(FuturePredictions.NewYearPrediction()) is really ugly. I am not sure how I missed this one. Here is what I did - I took IWriter and added it as a property to CoreClassDI like you suggested. Then, the same line became Writer.WriteMessage(FuturePredictions.NewYearPrediction());. Ofcourse the writer object and the prediction object are both constructor injection. –  TheSilverBullet Dec 24 '12 at 12:15
    
Posted the earlier comment before yours... I see what you are trying to say. My CoreClassDI will eventually be refined into the class IoC which I borrowed from Ken Egozi. Am I correct? –  TheSilverBullet Dec 24 '12 at 12:20
    
Thank you almaz, for your patience in answering me for both these questions! I value what I learnt in our discussions. –  TheSilverBullet Dec 24 '12 at 13:17
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.