Injection de dépendances #03 : Injection de dépendances en utilisant Ninject#

Dans cet article on va utiliser NInject pour faire de l’injection de dépendances au sein de l’exemple précédemment établit dans le premier article et modifié dans le second . Pour cela on va tout d’abord télécharger et installer NInject.

Ensuite on va ouvrir notre solution de l’exemple, et on va ajouter une référence dans le projet console vers la librairie Ninject.Core.dll.

clip_image002

NInject.Core est la librairie qui va nous permettre d’implémenter l’injection de dépendance.

Tout d’abord on doit commencer par déclarer les dépendances c'est-à-dire que telle interface correspond à telle implémentation, ceci se fait dans un « Module ».

Pour ce faire, on va tout simplement implémenter un module personnalisé et surcharger sa méthode load de la classe StandardModule fournie par NInject de la manière suivante :

    public class CustomModule : StandardModule
    {
       
public override void Load()
        {
           
//D?claration des d?pendances
            Bind<IPlat>().To<PattesBolognaises>();
            Bind<
IUstensile>().To<Marmitte>();
        }
    }

 

On dit dans la méthode load ci dessus que l’implémentation de l’interface IPlat est la classe PattesBlognaises, Idem pour IUstensile et Marmitte.

Pour résoudre les dépendances, il faut tout simplement instancier le container IKernel en lui passant le module qui va bien.

    class Program
    {
       
static void Main(string[] args)
        {
           
//Instanciation du module
            CustomModule module = new CustomModule();
           
//Instanciation du kernel charg? de r?soudre les d?pendances
            IKernel kernel = new StandardKernel(module);
           
//Demande de r?solution des d?pendances de Cuisinier 
            //et de retourner une instance
            Cuisinier p = kernel.Get<Cuisinier>();
           
Console.WriteLine(p.Cuisiner());

            Console.Read();
        }
    }

 

En faisant kernel.Get<Cuisinier>() on va demander au container de résoudre les dépendances de la classe Cuisinier et de nous en retourner une instance. On remarque au passage que la méthode Get est générique.

Voici ce qu’on retrouve à l’execution :

clip_image002[4]

Pour switcher d’une implémentation à une autre, on a 2 choix :

- 1er cas : On dit que c’est exclusif, c'est-à-dire qu’une interface correspond à une et une seule implémentation pour une instance de l’application, on va alors mettre des « case » dans le module pour choisir les implémentations à lier aux interfaces par rapport à un critère bien définit.

- 2ème cas : On dit que pour une instance de l’application une interface peut être liée à plusieurs implémentations. Dans ce cas, on est alors amené à implémenter plusieurs modules.

Le 1er cas étant déjà implémenté ci-dessus, je vais plutôt m’intéresser à implémenter le 2ème cas. Pour ce faire, je vais construire un nouveau module appelé RizModule qui va lier l’interface IPlat à l’implémentation RizAuCurry et l’interface IUstensile à l’implémentation Poelle comme suit :

    public class RizModule : StandardModule
    {
       
public override void Load()
        {
           
//D?claration des d?pendances
            Bind<IPlat>().To<RizAuCurry>();
            Bind<
IUstensile>().To<Poelle>();
        }
    }

 

Voici le programme main et son résultat :

    class Program
    {
       
static void Main(string[] args)
        {
           
//Instanciation du module
            CustomModule module = new CustomModule();
           
//Instanciation du kernel charg? de r?soudre les d?pendances
            IKernel kernel = new StandardKernel(module);
           
//Demande de r?solution des d?pendances de Cuisinier 
            //et de retourner une instance
            Cuisinier p = kernel.Get<Cuisinier>();
           
Console.WriteLine(p.Cuisiner());

           
//Instanciation du module
            RizModule rizModule = new RizModule();
           
//Instanciation du kernel charg? de r?soudre les d?pendances
            IKernel rizKernel = new StandardKernel(rizModule);
           
//Demande de r?solution des d?pendances de Cuisinier 
            //et de retourner une instance
            Cuisinier chefRiz = rizKernel.Get<Cuisinier>();
           
Console.WriteLine(chefRiz.Cuisiner());

           
Console.Read();
        }
    }

 

clip_image002[6]

Conclusion :

NInject est très simple à apprivoiser.

Le fait de pouvoir faire la liaison entre l’implémentation et l’interface par code à l’aide du « Bind » présente un l’avantage d’être du compilé et donc c’est moins générateur d’erreur qu’un fichier xml de configuration par exemple où on peut faire des fautes de frappe par exemple. En contre partie on ne dispose pas de la souplesse d’un fichier xml parce qu’à chaque fois qu’on aura envie de changer le Binding d’une interface à une implémentation on est obligé de recompiler le code, alors qu’avec un fichier xml il suffit de le mettre à jour.

Le container de NInject est générique, on récupère directement une instance de la classe souhaitée sans avoir besoin de faire un cast.

Le kernel résout récursivement les dépendances, c'est-à-dire qu’il résout les dépendances de l’objet mais aussi les dépendances des dépendances de l’objet … Ce qui nous facilite grandement le travail.

c#3 | DI | IOC | Ninject
Wednesday, November 26, 2008 12:34:54 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

 

All content © 2012, Zied Nemili