DCSIMG
Building a basic IoC - new { Name = ”Shay Jacoby” }

new { Name = ”Shay Jacoby” }

Maximum separation, minimum Dependencies, No Injections.

Building a basic IoC

I used to work with the IoC libraries Unity Application Block, StructureMap which I found very good but I wanted a very basic one that keeps the services/repositories as singleton, no need to manage state/lifetime of objects..

I didn't use one of the libraries I mentioned above because I don't need most of their functionallity.

So... I wrote my basic IoC and would like to share it with You:

Step 1 - App.Config/Web.config

<configSections>

    <!--Add this line inside "configSections" -->

    <section name="ioc" type="Framework.IoC.MappingSectionHandler, Framework.IoC, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce99303d14144e28"/>

</configSections>

 

Step 2 - Add object mapping table

 

add your mapping table after end of </configSections>:

 

Here's an example configuration from my current project:

   

<ioc>

     <!--Infrastracture components-->

     <!--<type name="Framework.Core.ILogger" mapTo="Framework.Logging.NLogLogger, Framework.Logging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce99303d14144e28"/>-->

     <type name="Framework.Core.ILogger" mapTo="Framework.Logging.Log4NetLogger, Framework.Logging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce99303d14144e28"/>

     <type name="Framework.Core.ICacheManager" mapTo="Framework.Caching.CacheManager, Framework.Caching, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce99303d14144e28"/>

     <type name="Framework.Core.IEmail" mapTo="Framework.Messaging.Email, Framework.Messaging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce99303d14144e28"/>

     <type name="Framework.Core.IValidation" mapTo="MvcValidation.NHibernateValidation, MvcValidation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce99303d14144e28"/>

 

      <type name="Framework.IRepository.IArticleRepository" mapTo="Framework.NHibernateRepository.ArticleRepository, Framework.NHibernateRepository"/>

     <type name="Framework.IRepository.IContactRepository" mapTo="Framework.NHibernateRepository.ContactRepository, Framework.NHibernateRepository"/>

     <type name="Framework.IRepository.IEventRepository" mapTo="Framework.NHibernateRepository.EventRepository, Framework.NHibernateRepository"/>

     <type name="Framework.VR.IRepository.IClientRepository" mapTo="Framework.VR.NHibernateRepository.ClientRepository, Framework.VR.NHibernateRepository"/>

</ioc>

 

 

Step 3 - Create a new class library project, I called it "Framework.IoC".

 

Step 4 - Add a new class called "MappingSectionHandler.cs" and paste the following code into it:

 

 

namespace Framework.IoC

{

 

    #region Using directives

 

    using System.Configuration;

    using System.Collections.Generic;

    using System.Xml;

 

    #endregion

 

    public class MappingSectionHandler : IConfigurationSectionHandler

    {

 

        #region IConfigurationSectionHandler Members

 

 

        /// <summary>

        /// Iterate through all the child nodes of the XMLNode that

        /// was passed in and extract the information into a Dictionary.

        /// </summary>

        /// <param name="parent">Parent object.</param>

        /// <param name="configContext">Configuration context object.</param>

        /// <param name="section">The XML section we will iterate against</param>

        /// <returns>The created section handler object.</returns>

        public object Create(object parent, object configContext, XmlNode section)

        {

            var dictionary = new Dictionary<string, string>();

 

            foreach (XmlNode item in section.ChildNodes)

                if (item.NodeType != XmlNodeType.Comment)

                    dictionary[item.Attributes["name"].Value] = item.Attributes["mapTo"].Value;

 

            return dictionary;

        }

 

        #endregion

 

    }

}

 
 
Step 5 - Add a new class called "Container" and paste the following code into it:
 


 

namespace Framework.IoC

{

 

    #region Using directives

 

    using System;

    using System.Collections.Generic;

    using System.Configuration;

    using Properties;

 

    #endregion

 

    /// <summary>

    /// The IoC Container static class provides inversion of control and service lookup functionality.

    /// </summary>

    public static class Container

    {

        /// <summary>

        /// static readonly dictionary to store the instances.

        /// </summary>

        private static readonly IDictionary<string, object> factories = new Dictionary<string, object>();

 

        /// <summary>

        /// Configuration Section name

        /// </summary>

        private const string sectionName = "ioc";

 

        /// <summary>

        /// some object to lock when filling the dictionary to rnsure thread safety.

        /// </summary>

        private static readonly object iocLock = new object();

 

        /// <summary>

        /// resolve a component of the specified <typeparamref name="T"/> type.

        /// </summary>

        /// <typeparam name="T">The type of component to resolve or build.</typeparam>

        /// <returns>An instance of <typeparamref name="T"/>.</returns>

        public static T Resolve<T>() where T : class

        {

            T factory;

 

            var key = typeof(T).FullName;

            object factoryItem;

 

            // See if the factory is in the cache

            if (factories.TryGetValue(key, out factoryItem))

            {

                // It was there, so retrieve it from the cache.

                factory = factoryItem as T;

            }

            else

            {

                // not in dictionary, let's create the factory.

 

                // Get the entityMappingsConfiguration config section

                var dictionary = (Dictionary<string, string>)ConfigurationManager.GetSection(sectionName);

                string typeName;

                if (!dictionary.TryGetValue(key, out typeName))

                    throw new ArgumentOutOfRangeException(string.Format(Resources.key_not_found, key));

 

                // Get the type to be created using reflection

                var factoryType = Type.GetType(typeName);

 

                // if factoryType is null throw.

                if (factoryType == null)

                    throw new NullReferenceException(typeName);

 

                // Create the factory using reflection

                factory = Activator.CreateInstance(factoryType) as T;

 

 

                lock (iocLock)

                {

                    // Put the newly created factory in the cache

                    factories[key] = factory;

                }

            }

 

            // if null than throw Exception.

            if (factory == default(T))

                throw new Exception(string.Format(Resources.cannot_instanciate, key));

 

            return factory;

 

        }

 

 

    }

}

 
 
Step 6 - see some example usages:
 
basic usage:

var logger = IoC.Container.Resolve<ILogger>();

logger.Debug("Sample message");

 
 
 
example class:
 

public class Accounts

    {

 

        private IRepository _repository;

 

        public Accounts()

        {

            _repository = Container.Resolve<IRepository>();

        }

 

 

 

        public void Save()

        {

            var account = new Account(1, "test");

            _repository.Save(account);

        }

 

    }

 
------------------------------------------------------
 
I added the code as post attachement.
Good Luck.

 
Shay.

תוכן התגובה

... כתב/ה:

The topic is quite curious, i must say

# November 4, 2008 9:06 AM

... כתב/ה:

Interessante Informationen.

# March 5, 2009 12:06 PM

c# – What is the overhead cost associated with IoC containers like StructureMap? | mywebsite כתב/ה:

Pingback from  c# &#8211; What is the overhead cost associated with IoC containers like StructureMap? | mywebsite

# July 7, 2012 5:11 PM
שלח תגובה

(שדה חובה)  

(שדה חובה)  

(אופציונלי)

(שדה חובה) 

Please add 8 and 7 and type the answer here:


Enter the numbers above: