Injection de dépendances #05 : Injection de dépendances à l’aide du projet Castle#

Dans cet article on va utiliser Castle Windsor 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 le projet Castle Windsor.

Comme tous les frameworks implémentant l’injection de dépendances, Castle Windsor met à disposition un container (ou Kernel) permettant de résoudre les dépendances. Il faut bien entendu signifier à ce dernier les dépendances avant de lui demander de les résoudre.

Côté implémentation c’est dans la même idée que Ninject, sauf qu’on peut déclarer les dépendances soit par code soit dans le fichier de configuration .config

On va commencer par ajouter les références aux librairies Castle nécessaires pour faire de l’injection de dépendances dans le projet console à savoir : Castle.Core.dll, Castle.MicroKernel.dll et enfin Castle.Windsor.dll.

Pour pouvoir charger ces dll, il suffit de rajouter à votre app.config les lignes suivantes :

 

<?xml version="1.0" encoding="utf-8" ?>
<
configuration>

...
        <
configSections>
                <
section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
        </
configSections>

...

</configuration>

 

Si vous n’avez pas de fichier .config dans votre projet, vous pouvez le rajouter en faisant click droit sur le projet -> Add -> New Item… et choisir l’élément « Application Configuration File »

Ensuite on va déclarer les dépendances au container de Castle, pour cet article j’ai choisi de la faire dans le fichier de config. Les deux types de classes qu’on va injecter pour notre exemple sont la classe RizAuCurry et la classe Poelle. Pour ce faire il faut rajouter ces quelques lignes dans le fichier de config :

 

<?xml version="1.0" encoding="utf-8" ?>
<
configuration>

...
        <
castle>
                <
components>

                        <
component id="Cuisinier"
                                           type="DemoLibrary.Implementation.Cuisinier, DemoLibrary">

                        </
component>
                        <
component id="Ustensile"
                                           service="DemoLibrary.Interfaces.IUstensile, DemoLibrary"
                                           type="DemoLibrary.Implementation.Poelle, DemoLibrary">

                        </
component>
                        <
component id="Plat"
                                           service="DemoLibrary.Interfaces.IPlat, DemoLibrary"
                                           type="DemoLibrary.Implementation.RizAuCurry, DemoLibrary">

                        </
component>

                </
components>
        </
castle>

...

</
configuration>

 

La balise Component nous permet de déclarer une dépendance. L’attribut id correspond au nom qui sera utilisé pour la résolution de dépendance, l’attribut service désigne l’interface à résoudre et est composé de 2 parties : le namespace + nom de l’interface et le nom de la dll. Enfin l’attribut type qui permet de spécifier le type de l’objet qui sera retourné par le kernel lors de la résolution de dépendance et qui est aussi composée de 2 parties : le namespace + nom de l’interface et le nom de la dll.

Maintenant il ne reste plus qu’à écrire le code principal dans notre projet console et au lieu d’instancier directement les classes on va demander au container Caste de nous renvoyer une instance du type dont on a besoin. Et ce qui est intéressant avec Castle c’est qu’on bénéficie de la résolution récursive de dépendances et qu’on n’a pas besoin de demander au container de résoudre toutes les dépendances une par une mais en faisant l’instanciation, à chaque fois qu’il va rencontrer une dépendance il va voir dans son fichier de config s’il peut la résoudre ce qui réduit considérablement le code à écrire.

    class Program
    {
       
static void Main(string[] args)
        {
           
//Instancier le container castle
            IWindsorContainer container =
           
new WindsorContainer(
               
new XmlInterpreter(new ConfigResource("castle")));

           
//Demande de r?solution des d?pendances de Cuisinier 
            //et de retourner une instance
            Cuisinier cuisinier = container.Resolve<Cuisinier>();

           
Console.WriteLine(cuisinier.Cuisiner());

           
Console.Read();
        }
    }

 

Voici le résultat :

 

clip_image002

Avantages :

- Le fait d’utiliser le fichier de config pour la déclaration de dépendances présente un avantage certain qui est de pouvoir changer le type retourné par le container sans avoir besoin de recompiler tout le code ;

- Simple à mettre en œuvre ;

- Le container est générique ;

- Résolution récursive de dépendances.

Inconvénients

- La déclaration de dépendances au sein du fichier de config peut être une source d’erreurs lors de l’exécution puisque ce n’est pas du compilé.

Conclusion :

L’implémentation de l’injection de dépendances au sein du framework Castle Windsor est très complète, souple et puissante. La prise en main est simple et le code à écrire se trouve réduit. La seule question qui reste ouverte c’est la question de la performance.

c#3 | Castle Project | DI | IOC
Friday, December 19, 2008 1:51:59 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

 

Injection de dépendances #04 : Injection de dépendances à l'aide de Spring.NET#

Dans cet article on va utiliser Spring.NET 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 Spring.NET.

Le framework Spring.NET est basé sur la version java du framework Spring. Il permet de faciliter et d'accélérer le développement d'applications .NET en proposant des implémentations de différentes fonctionnalités comme la programmation orientée aspect (AOP), l'accès aux données avec NHibernate ou encore l'injection de dépendances.

Comme tous les frameworks implémentant l’injection de dépendances, Spring.NET met à disposition un container permettant de résoudre les dépendances. Il faut bien entendu signifier à ce dernier les dépendances avant de lui demander de les résoudre.

Côté implémentation c’est totalement différent des implémentations des autres frameworks. La déclaration des dépendances se fait dans le fichier de configuration .config

On va commencer par ajouter la référence à Spring.Core.dll dans le projet console.

Pour pouvoir charger cette dll, il suffit de rajouter à votre app.config les lignes suivantes :

 

<?xml version="1.0" encoding="utf-8" ?>
<
configuration>

...
        <
configSections>
                <
sectionGroup name="spring">
                        <
section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
                        <
section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
                </
sectionGroup>
        </
configSections>

...
</
configuration>

 

Si vous n’avez pas de fichier .config dans votre projet, vous pouvez le rajouter en faisant click droit sur le projet -> Add -> New Item… et choisir l’élément « Application Configuration File »

Ensuite on va déclarer les dépendances au container de Spring. En fait en ce qui concerne Spring on définit des alias sur les types qu’on veut injecter. Les deux types de classes qu’on va injecter pour notre exemple sont la classe RizAuCurry et la classe Poelle. Pour ce faire il faut rajouter ces quelques lignes suivantes dans le fichier de config :

 

<?xml version="1.0" encoding="utf-8" ?>
<
configuration>

...


        <
spring>
                <
context>
                        <
resource uri="config://spring/objects" />
                </
context>
                <
objects xmlns="http://www.springframework.net">
                        <
object name="Plat" type="DemoLibrary.Implementation.RizAuCurry, DemoLibrary" singleton="false" />
                        <
object name="Ustensile" type="DemoLibrary.Implementation.Poelle, DemoLibrary" singleton="false" />
                </
objects>
        </
spring>

...

</
configuration>

 

La balise Object nous permet de définir un alias vers un type. L’attribut name correspond à l’alias, l’attribut type est composé de 2 parties : le namespace + nom de la classe et le nom de la dll. Enfin l’attribut singleton permet de spécifier si c’est un singleton.

Ensuite, on va créer un « wrapper » sur le container de Spring, qui va juste nous renvoyer le container lorsqu’on en a besoin. On pourrait bien évidemment se passer de cette étape mais un peu d’organisation ça ne fait pas de mal.

using Spring.Context;
using Spring.Context.Support;

    public static class Context
    {
       
private static IApplicationContext applicationContext = null;

       
static Context()
        {
            applicationContext =
ContextRegistry.GetContext();
        }

       
public static IApplicationContext ApplicationContext
        {
           
get { return applicationContext; }
        }

    }

 

Maintenant il ne reste plus qu’à écrire le code principal dans notre projet console et au lieu d’instancier directement les classes on va demander au container Spring de nous renvoyer une instance du type dont on a besoin.

    class Program
    {
       
static void Main(string[] args)
        {
           
//Le container Spring renvoye un objet qui
            //correspond ? l'alias Plat
            IPlat plat = (IPlat)Context.ApplicationContext["Plat"];

           
//Le container Spring renvoye un objet qui
            //correspond ? l'alias Ustensile
            IUstensile ustensile = (IUstensile)Context.ApplicationContext["Ustensile"];

           
//Instaciation de la classe Cuisinier
            Cuisinier chef = new Cuisinier(ustensile,plat);
            
           
Console.WriteLine(chef.Cuisiner());

           
Console.Read();
        }
    }
 

 

Voici le résultat :

image

Avantages

L’implémentation de l’injection de dépendances avec le framework Spring.NET offre beaucoup d’avantages :

- Le fait d’utiliser le fichier de config pour la déclaration des alias présente un avantage certain qui est de pouvoir changer la classe vers laquelle pointe un alias sans avoir besoin de recompiler tout le code.

Inconvénients

- Pas de résolution récursive de dépendances, on doit explicitement demander au container les objets correspondant aux alias dont on a besoin.

- Le container n’est pas générique ce qui nous oblige à faire un cast à chaque fois que ce dernier nous renvoie un objet.

- La déclaration des alias au sein du fichier de config peut être une source d’erreurs lors de l’exécution puisque ce n’est pas du compilé.

Conclusion :

Spring.NET est un bon framework d’injection de dépendances grâce à son côté souple concrétisé par l’utilisation du fichier de config mais je dois avouer que le fait de ne pas avoir la résolution récursive de dépendances est un inconvénient non négligeable et qui est à mon avis éliminatoire au sein d’un grand projet.

c#3 | DI | IOC | Spring
Thursday, December 18, 2008 11:44:47 PM (Romance Standard Time, UTC+01:00) #    Comments [2]  | 

 

All content © 2012, Zied Nemili