59 votes

Qu'est-ce que Ninject et quand l'utilisez-vous?

J'ai aidé quelques amis sur un projet et il y a une classe qui utilise Ninject. Je suis assez novice en C# et je n'ai aucune idée de ce que la classe est en train de faire, c'est pourquoi j'ai besoin de comprendre Ninject. Quelqu'un peut-il expliquer ce que Ninject est et quand doit-on utiliser(avec un exemple si possible)? Ou si vous avez des liens ce serait très bien aussi.

J'ai essayé cette question: Ninject tutoriels/documentations? mais il n'a pas vraiment aider un débutant comme moi.

49voto

nsinreal Points 1013

Ninject est la dépendance de l'injecteur pour .NET, la réalisation pratique du modèle d'Injection de Dépendance (formule d'Inversion de modèle de Contrôle).

Supposons que vous avez deux classes DbRepository et Controller:

class Controller {
   private DbRepository _repository;

   // ... some methods that uses _repository
}

class DbRepository {
   // ... some bussiness logic here ...
}

Alors, maintenant, vous avez deux problèmes:

  1. Vous devez inialize _repository à l'utiliser. Vous avez de telles façons:

    1. Dans le constructeur manuellement. Mais que faire si le constructeur de DbRepository changements? Vous avez besoin de réécrire votre Controller classe parce que l'autre partie du code a été changé. Il n'est pas difficile si vous avez un seul Controller, mais si vous avez un couple de classes qui ont dépendance sur votre Repository vous avez un réel problème.
    2. Vous pouvez utiliser le localisateur de service ou à l'usine ou qch. Maintenant, vous avez la dépendance à votre service locator. Vous avez un service global locator et tout le code doit l'utiliser. Comment vous changera les comportements de localisateur de service lorsque vous en avez besoin pour utiliser sur une partie de code d'une logique de l'activation et de quelque chose d'autre dans l'autre partie de code? Il est seulement un moyen de transmission de service locator par les constructeurs. Mais avec de plus en plus de classes, vous aurez besoin de passer de plus en plus. De toute façon, c'est bonne idée, mais c'est une mauvaise idée.

      class Controller {
         private DbRepository _repository;
      
         public Controller() {
           _repository = GlobalServiceLocator.Get<DbRepository>()
         }
      
         // ... some methods that uses _repository
      }
      
    3. Vous pouvez utiliser l'injection de dépendance. Regarde le code:

      class Controller {
         private IRepository _repository;
      
         public Controller(IRepository repository) {
            _repository = repository;
         }
      }
      

    Maintenant, quand vous avez besoin de votre contrôleur, vous écrivez: ninjectDevKernel.Get<Controller>(); ou ninjectTestKernel.Get<Controller>();. Vous pouvez basculer entre la dépendance des résolveurs aussi vite que vous le souhaitez. Voir? C'est simple, vous n'avez pas besoin d'écrire beaucoup.

  2. Vous ne pouvez pas faire des tests unitaires sur elle. Votre Controller ont dépendance de l' DbRepository et si vous voulez tester une méthode qui utilise le référentiel, votre code de base de données et lui demander les données. C'est lent, très lent. Si votre code en DbRepository changements, votre unité de test sur Controller va tomber. Seule l'intégration de test doit dire "problèmes" dans ce cas. Ce dont vous avez besoin dans les tests unitaires - pour isoler vos classes et test d'une classe unique dans un test (dans l'idéal, une seule méthode). Si votre DbRepository code échoue, vous allez penser que Controller code échoué, et que c'est mal (même si vous avez des tests pour DbRepository et Controller - ils seront tous les deux échouer et vous pouvez commencer à partir de mauvais endroit). Il faut beaucoup de temps pour déterminer où est l'erreur vraiment. Vous devez savoir que certains de la classe est ok, et quelques autres de la classe a échoué.

  3. Lorsque vous souhaitez remplacer DbRepository avec autre chose dans toutes vos classes, vous devez faire beaucoup de travail.

  4. Vous ne pouvez pas simple de contrôle de la durée de vie d' DbRepository. Objet de cette classe crée sur inializing d' Controller et supprime lorsqu' Controller supprime. Il n'y a pas de partage entre les différentes instances de l' Controller de la classe et il n'y a pas de partage entre les autres classes. Avec Ninject, vous pouvez simplement écrire:

    kernel.Bind<IRepository>().To<DbRepository>().InSingletonScope();
    

Et la particularité de l'injection de dépendance - développement agile! Vous décrire ce que votre contrôleur utilise un référentiel avec interface IRepository. Vous n'avez pas besoin d'écrire DbRepository, vous pouvez écrire un texte simple MemoryRepository de la classe et de développer Controller alors que les autres gars se développe DbRepository. Lors de l' DbRepository sera terminé, vous venez de lie de nouveau dans votre résolution de dépendances que par défaut IRepository est DbRepository maintenant. Vous avez écrits beaucoup de contrôleurs? Tout d'entre eux utilisent maintenant l' DbRepository. C'est cool.

Lire la suite:

  1. L'Inversion de contrôle (wiki)
  2. L'injection de dépendance (wiki)
  3. L'Inversion de Contrôle des Conteneurs et l'Injection de Dépendance modèle (Martin Fowler)

41voto

Sklivvz Points 16412

Ninject est une Inversion de Contrôle conteneur.

Que faut-il faire?

Supposons que vous avez un Car classe qui dépend de l' Driver classe.

public class Car 
{
   public Car(IDriver driver)
   {
      ///
   }
}

Afin d'utiliser l' Car classe que vous le construire comme suit:

IDriver driver = new Driver();
var car = new Car(driver);

Un Cio containter centralise les connaissances sur la façon de créer des classes. C'est un référentiel central qui en sait bien peu de choses. Par exemple, il sait que la classe de béton que vous devez utiliser pour construire une voiture est un Driver et non pas un autre IDriver.

Par exemple, si vous développez une application MVC, vous pouvez dire Ninject comment construire vos contrôleurs. Vous le faites en vous inscrivant concrètes qui répond à des interfaces spécifiques. Au moment de l'exécution Ninject va déterminer les classes sont nécessaires pour construire le contrôleur requis, et tous derrière les coulisses.

// Syntax for binding
Bind<IDriver>().To<Driver>();

Ceci est intéressant, car il permet de construire des systèmes qui sont plus facilement unité vérifiable. Supposons qu' Driver encapsule tous les accès de base de données pour Car. Dans un test unitaire pour la Voiture, vous pouvez faire ceci:

IDriver driver = new TestDriver(); // a fake driver that does not go to the db
var car = new Car(driver);

Il y a toute les cadres qui prennent soin de créer automatiquement des tests de classe pour vous et ils sont appelés les moqueries des cadres.

Pour plus d'informations:

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X