Простой IoC-контейнер на 90 строк

Posted: Январь 3, 2011 in .NET

Мне нравится DSL у StructureMap:

ObjectFactory.Initialize(x =>
   {
       x.For<IValidator>().Use<Validator>();
   });

IValidator validator = ObjectFactory.GetInstance<IValidator>();

Именно этот сценарий я использую в 80% случаев, и очень захотелось изобрести велосипед. Понятно, что чтобы сделать такое, нужно иметь какую-то статическую коллекцию (скорее всего словарь), куда при инициализации нужно класть интерфейсные типы в качестве ключей, а подходящие типы в качестве значений, и при использовании — извлекать.
Поковырявшись 5 минут в исходниках находим, что делегат в Initialize это

Action<T>

А в качестве коллекции действительно используется словарь))) Вот что в итоге получилось (названия классов также взяты из StructureMap):

namespace Zizoc
{
    using System;
    using System.Collections.Generic;

    #region ObjectFactory
    public class ObjectFactory
    {
        private static readonly object _lockObject = new object();
        private readonly static Dictionary<Type, Type> _defaults = new Dictionary<Type, Type>();

        public static void Initialize(Action<InitializationExpression> action)
        {
            action(new InitializationExpression());
        }

        public static void AddType(Type pluginType, Type concreteType)
        {
            lock (_lockObject)
            {
                if (_defaults.ContainsKey(pluginType))
                {
                    _defaults[pluginType] = concreteType;
                }
                else
                {
                    _defaults.Add(pluginType, concreteType);
                }
            }
        }

        public static PLUGINTYPE GetInstance<PLUGINTYPE>() 
            where PLUGINTYPE: class
        {
            var t = typeof(PLUGINTYPE);

            lock (_lockObject)
            {
                if (_defaults.ContainsKey(t))
                {
                    return (Activator.CreateInstance(_defaults[t]) as PLUGINTYPE);
                }
            }

            return null;
        }

        public static void RemoveType(Type pluginType)
        {
            lock (_lockObject)
            {
                if (_defaults.ContainsKey(pluginType))
                {
                    _defaults.Remove(pluginType);
                }
            }
        }
    }
    #endregion

    #region InitializationExpression
    public class InitializationExpression
    {
        public CreatePluginFamilyExpression<PLUGINTYPE> For<PLUGINTYPE>()
        {
            return new CreatePluginFamilyExpression<PLUGINTYPE>(this);
        }
    }
    #endregion

    #region CreatePluginFamilyExpression
    public class CreatePluginFamilyExpression<PLUGINTYPE>
    {
        public CreatePluginFamilyExpression(InitializationExpression init)
        {
        }

        public CreatePluginFamilyExpression<PLUGINTYPE> Use<CONCRETETYPE>()
         where CONCRETETYPE : PLUGINTYPE
        {
            var pluginType = typeof(PLUGINTYPE);
            var concreteType = typeof(CONCRETETYPE);

            ObjectFactory.AddType(pluginType, concreteType);

            return null;
        }
    }
#endregion
}

Очень простой IoC-контейнер для конфигурации приложения.

Реклама

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s