Проблемы с пониманием ninject (или просто IOC-контейнера в целом) по сравнению с фабричным DI?

Хорошо, так что недавно я читал в ninject, но у меня проблемы с пониманием того, что делает его лучше, чем то, почему они назвали DI "бедным человеком" на странице вики. Самое печальное, что я просмотрел все их страницы в вики и все еще не понял =(.

Обычно я оборачиваю свои сервисные классы в паттерн фабрики, который обрабатывает DI следующим образом:

public static class SomeTypeServiceFactory
{
    public static SomeTypeService GetService()
    {
        SomeTypeRepository someTypeRepository = new SomeTypeRepository();
        return = new SomeTypeService(someTypeRepository);

    }

}

Что мне кажется очень похожим на модули:

public class WarriorModule : NinjectModule {
    public override void Load() {
      Bind<IWeapon>().To<Sword>();
      Bind<Samurai>().ToSelf().InSingletonScope();
    }
}

Где каждый класс имеет свой модуль, и вы привязываете его конструктор к конкретной реализации. Хотя код ninject на 1 строку меньше, я просто не вижу преимущества, в любое время, когда вы добавляете/удаляете конструкторы или изменяете реализацию конструктора интерфейса, вам придется изменить модуль практически так же, как и фабрику, нет? Так что не вижу здесь преимущества.

Затем я подумал, что мог бы придумать фабрику, основанную на общих соглашениях, например, так:

 public static TServiceClass GetService<TServiceClass>()
        where TServiceClass : class
    {
        TServiceClass serviceClass = null;

        string repositoryName = typeof(TServiceClass).ToString().Replace("Service", "Repository");
        Type repositoryType = Type.GetType(repositoryName);

        if (repositoryType != null)
        {
            object repository = Activator.CreateInstance(repositoryType);
            serviceClass =  (TServiceClass)Activator.CreateInstance(typeof (TServiceClass), new[]{repository});
        }

        return serviceClass;
    }

Однако, это плохо по двум причинам: 1) Она сильно зависит от соглашения об именовании, 2) Она предполагает, что у хранилища никогда не будет никаких конструкторов (это не так) и единственным конструктором сервиса будет соответствующее репо (тоже не так). Мне сказали "эй, здесь нужно использовать IoC-контейнер, это было бы здорово!" И таким образом началось мое исследование... но я просто не вижу и не могу понять этого...

Есть ли какой-то способ, которым ninject может автоматически разрешать конструкторы класса без конкретного объявления, что было бы здорово использовать в моей общей фабрике (я также понимаю, что я мог бы сделать это вручную, используя отражение, но это падение производительности, а ninject прямо на своей странице говорит, что не использует отражение).

Просветите по этому вопросу и/или покажите, как это можно использовать в моей общей фабрике, буду очень признателен!

EDIT: Ответ

Итак, благодаря объяснению ниже я смог полностью понять всю крутость ninject и моя generic factory выглядит так:

public static class EntityServiceFactory
{
    public static TServiceClass GetService<TServiceClass>()
        where TServiceClass : class
    {
        IKernel kernel = new StandardKernel();

        return kernel.Get<TServiceClass>();
    }
}

Довольно круто. Все обрабатывается автоматически, поскольку конкретные классы имеют неявное связывание.

6
задан SventoryMang 26 January 2012 в 22:04
поделиться