2010-09-28 14 views
6

J'ai lu à propos des cadres de l'inversion de contrôle et je suis tout simplement jouer avec la question suivante: « Pourquoi diable ai-je besoin d'un cadre pour le faire? » Ne pas mal compris ma question ... le modèle est quelque chose que nous les programmeurs utilisent souvent mais ... un cadre complet pour cela?Pourquoi utiliser un cadre IoC

Je dois manquer quelque chose et c'est la raison pour laquelle je pose la question. J'ai vu beaucoup d'exemples sur le web et je ne comprends pas. L'esprit mi est bloqué à l'idée peut-être.

Il suffit de jeter un oeil à l'exemple de la page Ninject Accueil:

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>(); 
    } 
} 

La classe "Samurai" est ok pour moi. Le cadre "NinjectModule" me semble inutile.

Je suppose plus tard dans le code que nous allons créer de nouvelles instances « Samurai » en passant dans les cas « épée » à lui, quelque chose comme:

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

qui pourrait être remplacé par:

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

ou

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

Quelle est la partie que je suis absent? Pourriez-vous s'il vous plaît parler d'un scénario où le cadre Ioc pourrait être nécessaire dans ma demande?

Merci.

mise à jour après 4 REPONSES: J'ai vraiment aimé toutes les réponses que j'ai obtenu de vous les gars. Je viens de lire ce post dependency-injection-dissection/ où le gars l'utiliser pour tester l'unité et le lien StackOverflow que vous venez de donner et Ouais, je manque le grand-grand-grande complexité partie, alors laissez-moi la coutume d'utiliser un cadre IoC. Merci encore.

Je voterais vos réponses, mais je viens de recevoir un message orange disant que je ne peux pas.

Merci au gars qui a mis en évidence le code que j'ai posté.

+1

Je suggère de modifier votre question pour que les blocs de code blocs de code réels, soit 'mettre en évidence et en appuyant sur Ctrl-k 'ou en insérant quatre espaces devant chaque ligne de code. – jcolebrand

+0

'new Samurai (new Sword()); // toujours pas de couplage' Il y a un couplage serré ici, vous utilisez 'new'. Quand vous refactorisez cela, vous devrez changer chaque endroit qui instancie une épée. – nos

+0

duplicata possible de [Pourquoi ai-je besoin d'un conteneur IoC par opposition au code DI simple?] (Http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed -to-simple-di-code) –

Répondre

4

Votre exemple est d'avoir assez simple juste les deux couches, mais quand vous avez un exemple concret de la vie, il va très vite en désordre:

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

Un conteneur IoC peut faire tout le câblage pour vous, ce qui rend votre la vie beaucoup plus facile.

Voici un exemple d'une question similaire, qui va dans tous les détails: https://stackoverflow.com/questions/45191/ioc-explain-and-more-important-when-to-use-it/45197#45197

+0

Comment un conteneur IoC réduit-il la complexité? Je veux dire que vous auriez toujours définir l'arbre entier, mais vous devez utiliser une autre langue qui est plus sujette aux erreurs. –

6

Ceci est le problème avec les exemples de code. Ils sont complexes et vous n'avez pas expliqué votre point de vue, ou ils sont triviaux et semblent inutiles. Ce que le WarriorModule fait est de lier un type concret à une interface, et donc lorsqu'une autre classe a besoin d'une implémentation de cette interface, elle en reçoit une automatiquement par le conteneur IoC. La classe avec la dépendance n'a aucune dépendance sur le type concret, et a donc un couplage plus faible et une testabilité plus élevée. Je pense que tu le savais déjà.

Dans vos scénarios de remplacement, la classe Samurai n'est pas couplé à la classe d'épée, mais le code d'appel est encore. Vous pourriez pousser un autre niveau, mais ce code aurait maintenant la dépendance, et votre classe intervenante devrait maintenant rassembler toutes les dépendances.

Le conteneur IoC fait pour toutes les applications, mettre en quelques endroits (les classes de modules). Le reste de votre code est libre de ne pas s'en soucier, de ne pas avoir de dépendances sur des types concrets.

espoir qui aide.

+0

Aimer ce commentaire; "C'est le problème avec les exemples de code, ils sont complexes et vous n'avez pas expliqué votre point, ou ils sont triviaux et semblent inutiles." Je dirais habituellement plus à ce dernier. Particulièrement avec Ninject, aucun des exemples donnés ne justifie son utilisation parce qu'ils sont simplement trop simples, et ne démontrent aucun des détails qui le rendent utile au-delà de la DI manuelle. –

+0

Si vous avez un bon design, vous n'avez pas beaucoup de couplage du tout. Et où est la différence si je définis le câblage avec XML ou code à un endroit? –

1

J'ai récemment commencé à utiliser l'Unity for IoC et ne fait aucun doute que cela me rend la vie plus facile.

Je vais simplement coller mon code verbatim et j'espère que vous le trouverez utile. Quelqu'un de plus expérimenté pourrait vous en donner plus.

De plus, j'ai trouvé utile de lire l'article sur la DI par Fowler.

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); 
     } 
    } 

L'une des choses que je trouve le plus utile est la suivante:

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

Bien que Samurai theWarrior = new Samurai(new Sword()); est toujours pas de couplage, si vous voulez donner à tous les samouraïs dans votre application un <insert favourite weapon here>, vous devez changer tout votre code d'appel pour changer à la nouvelle arme, tandis qu'avec IoC vous le changeriez en un endroit et tous vos samouraïs utiliseraient la nouvelle arme.