2010-09-28 2 views
6

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

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

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

Просто взгляните на примере на 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?

Спасибо.

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

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

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

+1

Я хотел бы предложить редактирование вопроса, чтобы сделать блоки кода фактических блоков кода, либо 'подсветки и нажав Ctrl-K 'или вставив четыре пробела перед каждой строкой кода. – jcolebrand

+0

'new Samurai (новый Sword()); // до сих пор нет связи. Здесь есть жесткая связь, вы используете' new'. Когда вы реорганизуете это, вам придется менять каждое место, создающее Меч. – nos

+0

Возможный дубликат [Почему мне нужен контейнер IoC, а не простой код DI?] (Http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed -to-straight-di-code) –

ответ

4

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

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

+0

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

6

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

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

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

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

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

+0

Liking this comment; «Это проблема с образцами кода. Они сложны, и вы не объяснили свою точку зрения, или они тривиальны, а затем кажутся бессмысленными». Я бы сказал, что обычно больше для последнего. В частности, с Ninject ни один из приведенных примеров не оправдывает его использование, потому что они просто слишком просты и не демонстрируют никаких деталей, которые делают его стоящим выше и вне ручного DI. –

+0

Если у вас хороший дизайн, у вас совсем нет сцепления. И где же разница, если я определяю проводку с XML или кодом в одном месте? –

1

Недавно я начал использовать 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; } 
} 
1

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

Смежные вопросы