Saturday, September 29, 2012

How to implement a simple IoC Container.

I have decided to take a topic related to software development and dig deeper and write about it on weekends. It will be my weekly learning and knowledge sharing. I have myside projects but its always cool and rewarding to understand how something really works. I do not only want to be a framework user but also a Framework contributor. This can only happen if you deep deeper most of the tools of software and language you use. For this week I want to see how easy is it to implement a simple IoC container that can be used in a project.

 What is an IoC container ?
IoC stands  for Inversion of Control and represents a design pattern used in software development. Wikipedia describes it as " a style of software construction where reusable code controls the execution of problem-specific code. It carries the strong connotation that the reusable code and the problem-specific code are developed independently, which often results in a single integrated application. Inversion of control as a design guideline serves the following purposes:

  • There is a decoupling of the execution of a certain task from implementation.
  • Every module can focus on what it is designed for.
  • Modules make no assumptions about what other systems do but rely on their contracts.
  • Replacing modules has no side effect on other modules. "

 What problem does it try to solve?
 Coupling and dependencies between objects .We let some other objects inject the object when we need it hence we are inverting the control of the process .Passing interfaces into classes and not real objects makes it easy to maintain, add and extend functions of a  feature in an application.

What are the basic prerequisites of building one?
  1. You need a container class.
  2.  In the container class you need a delegate ( A function on the fly!)
  3.  You need a dictionary data structure since you need to look up for keys before sending out objects
  4. Create a function to register the interfaces
  5. Create another function to resolve the interfaces
  6. Use the Container and do something with it.

 Before looking at the code you should understand some concepts like Interfaces, Generics and Delegates in C#. The goal is not build something that I will actually use for production code but just to see and learn the core and basic aspects of an IOC container. Here is the code of the whole project.

   
    /*IOC Container main class */
    public class MyIocContainer
    {
        public delegate object CreateInstance(MyIocContainer container);

        public Dictionary Factory;

        public MyIocContainer()
        {
            this.Factory = new Dictionary();
        }

        public void RegisterInterface(CreateInstance ci)
        {
            if (ci == null)
                throw new ArgumentNullException("ci");

            if (Factory.ContainsKey(typeof(T)))
                throw new ArgumentException("Type already registered");

            Factory.Add(typeof(T), ci);
        }
         
        public T Resolve()
        {
            if (!Factory.ContainsKey(typeof(T)))
                throw new ArgumentException("Type not registered");

            // retrieve the object from the dictionary
            var creator = Factory[typeof(T)];

            // call the delegate returning the object created
            return (T)creator(this);
        }      
    }

   // Create some interfaces to use
    public interface IDownloader
    {
        void GetWebSiteContents(string url);
    }

    public interface IExtractHtmlTags
    {
        void ExtractHtmlTags(string pWebsiteHtmlP);
    }

    // Create some classes to use the interfaces 
    public class WebSiteDownLoader : IDownloader
    {
        public void GetWebSiteContents(string url)
        {   //Some code using the webclient class
            Console.WriteLine("Call using the IoC container to load a website");
        }
    }
   
    public class ExtractHtmlTag : IExtractHtmlTags
    {
        public void ExtractHtmlTags(string websiteDataStream)
        {   
            // Some code here using Regex class<.*?>
            Console.WriteLine("Call using the IoC container to extract html tags");
        }
    }

    // Usage class for the interfaces to perform task.
    public class WebSiteTagRemover
    {
        private readonly IExtractHtmlTags _extractHtml;
        private readonly IDownloader _getWebSite;

     public WebSiteTagRemover(IExtractHtmlTags eTag, IDownloader loader)
        {
           _extractHtml = eTag;
            _getWebSite = loader;
        }

     public void PrintResults()
        {
          _getWebSite.GetWebSiteContents("http://ngalatalla.blogspot.se/");
          _extractHtml.ExtractHtmlTags("website html

");
        }
    }
 
  /*Finally execute and use the container Hooray!! */
internal class Program
    {
        private static void Main(string[] args)
        {   
         //Initiate the container
            var container = new MyIocContainer();

        //Register some interfaces to be used
           container.RegisterInterface(x => new WebSiteDownLoader());
           container.RegisterInterface(x => new ExtractHtmlTag());

      //Resolve the interfaces and get the objects mapped to them
            var getContents = container.Resolve();
            var extract = container.Resolve();

        //Do stuff with the interfaces
        var webTagRemover = new WebSiteTagRemover(extract, getContents);
        webTagRemover.PrintResults();
        }
    }

Results---

If you really want to use an IoC Container in any .Net project, you do not need to implement your own. There are much better options out there. Even if you think of implementing your own, I do not think you can implement any feature or features that they do not already have. They are even more mature and free to use in your projects. Here is a list I composed for some popular ones. I use Ninject in my personal projects because it is mature and easily configured. Choose your own based on your needs.
  Happy programming !

Machine learning is the future

I am very enthusiastic about machine learning and the potential it has solve tough problems. Considering the fact that the amount of data we...