Зачем использовать IoC Framework - PullRequest
6 голосов
/ 28 сентября 2010

Я читал об инфраструктурах Inversion of Control, и я просто играю с вопросом: «Почему, черт возьми, мне нужна среда для этого?»

Не поймите неправильно мой вопрос ... шаблон - это то, что мы, программисты, часто используем, но ... полнофункциональный фреймворк для этого?

Я, должно быть, что-то упустил, и именно поэтому я задаю вопрос. Я видел много примеров в Интернете, и я просто не понимаю. Возможно, мой разум заблокирован этой идеей.

Просто взгляните на пример домашней страницы Ninject:

public class Samurai {
    public IWeapon Weapon { get; private set; }
    public Samurai(IWeapon weapon) {
        Weapon = weapon;
    }
}

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

Класс "Самурай" мне подходит. Мне не нужен фреймворк NinjectModule.

Я предполагаю, что позже в коде мы будем создавать новые экземпляры "Самурая", передавая ему экземпляры "Меча", что-то вроде:

Samurai theWarrior = new Samurai(WarriorModule.GetInstance(IWeapon));//no coupling

который может быть заменен на:

Samurai theWarrior = new Samurai(new Sword());//still no coupling

или

Samurai theWarrior = new Samurai(GetWeaponFromXML());//no coupling yet

Какая часть мне не хватает? Не могли бы вы рассказать о каком-либо сценарии, где Ioc Framework может понадобиться в моем приложении?

Спасибо.

ОБНОВЛЕНИЕ ПОСЛЕ 4 ОТВЕТОВ : Мне действительно понравились все ответы, которые я получил от вас, ребята. Я только что прочитал этот пост зависимость-инъекция-диссекция / , где парень использует его для модульного тестирования и ссылку на StackOverflow, которую вы только что предоставили, и да, я упустил часть сложности "большой-большой-большой", так что давайте сам использовать фреймворк IoC. Еще раз спасибо.

Я бы проголосовал за ваши ответы, но я просто получил оранжевое сообщение о том, что не могу.

Спасибо парню, который выделил код, который я разместил.

Ответы [ 4 ]

6 голосов
/ 28 сентября 2010

Это проблема с примерами кода. Они либо сложны, и вы не объяснили свою точку зрения, либо они тривиальны и кажутся бессмысленными.

То, что делает WarriorModule, привязывает конкретный тип к интерфейсу, и поэтому, когда другому классу требуется реализация этого интерфейса, он автоматически получает его с помощью контейнера IoC. Класс с зависимостью не зависит от конкретного типа, поэтому имеет более низкую связь и более высокую тестируемость. Я думаю, ты уже знал это.

В ваших сценариях замены класс самураев не связан с классом меча, но код вызова по-прежнему есть. Вы можете вытолкнуть это на другой уровень, но этот код теперь будет иметь зависимость, и ваш промежуточный класс теперь должен будет маршалировать все зависимости.

Контейнер IoC делает это для всех отображений, помещая его только в несколько мест (классы модуля). Остальная часть вашего кода свободна, чтобы не заботиться и не зависеть от конкретных типов.

Надеюсь, это поможет.

4 голосов
/ 28 сентября 2010

Ваш пример довольно прост, имея только два слоя, но когда у вас есть реальный пример, он скоро становится грязным:

var form = new OrderEntryForm(
    new OrderService(
        new OrderReposity(
            new DatabaseGateway(
                new DataProviderFactory()))))

Контейнер IoC может выполнить всю проводку за вас, делаяВаша жизнь намного проще.

Это пример из аналогичного вопроса, который включает все детали: https://stackoverflow.com/questions/45191/ioc-explain-and-more-important-when-to-use-it/45197#45197

1 голос
/ 28 сентября 2010

Хотя Samurai theWarrior = new Samurai(new Sword()); по-прежнему не является связующим звеном, если вы захотите присвоить всем самураям в вашем приложении <insert favourite weapon here>, вам придется изменить весь свой код вызова, чтобы перейти на новое оружие, тогда как с IoC вы бы изменили это в одном месте, и все ваши самураи будут использовать новое оружие.

1 голос
/ 28 сентября 2010

Я недавно начал использовать Unity для IoC, и не сомневаюсь, что это облегчит мою жизнь.

Я просто вставлю в свой код дословно и надеюсь, что вы найдете его полезным.Кто-то более опытный может дать вам больше.

Кроме того, я нашел полезным прочитать статью Фаулера о DI.

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        using (IUnityContainer container = new UnityContainer())
        {
            container

                .RegisterType<ILogger, StatSyncherFormView>(new myLife())

                // GUI
                .RegisterType<IStatSyncherView, StatSyncherFormView>()

                // Services
                .RegisterType<ISalesForceWebServices, SalesForceWebServices1>()

                .RegisterInstance(new SalesForceWebServices1(
                    "XXX", "XXX",
                   "https://login.salesforce.com/services/Soap/c/19.0/0DF70000000CfHq",
                    "https://na5-api.salesforce.com/services/Soap/s/19.0"))


                .RegisterType<ISalesForceService, SalesForceService1>()

                .RegisterType<IRestApiCall, RestApiCall1>()

                .RegisterType<IDirectTrackService, DirectTrackService1>()

                .RegisterType<IDAgentsService, DAgentsService1>()

                .RegisterType<IQuickBooksService, QuickBooksService1>();

            StatSyncherPresenter p = container.Resolve<StatSyncherPresenter>();

            Application.Run((Form)p.view);
        }
    }

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

public class AnyClassCreatedByContainer
{
    [Dependency]
    public ILogger Logger { get; set; }
}
...