Publiée le décembre 31, 2011 16:54

| nombre de lecture : 997
Introduction à Castle Windsor en C#
Castle est un ioc container, c.à.d un "inversion of control". Pour résumer c'est un peu l'inverse d'une API. Quand on utilise une API on développe son application et on invoque ses API pour des process particuliers (backend). Dans le cas de Castle, il s'agit plutot d'une couche intermédiaire entre le back-end et le frond-end qui permet en fait d'hériter de son IOC Container des comportements généraux réutilisables par son application... Un peu comme si le container nous fournissez un ensemble de fonctionnalité en se greffant sur notre code.
Le but des IOC container est avant tout de nous faciliter certaines tâches comme les tests, les installers, la maintenance du backend.
Après avoir joué avec même si cela a des avantages, un peu comme pour nHibernate, je reste moyennement fan, mais c'est une pratique up-to-date carrée et qui donc mérite d'être utilisée, avec les mêmes contraintes que pour NHibernate, une légère perte de performance, et en cas de galère faut trouvé un gourou pour régler cela.
Objectif du tutorial
L'objectif de ce tuto est de vous faire découvrir Castle Windsor de manière assez basique. Le but étant d'avoir un message sur un écran webform asp.net du genre <prénom> says: Hello World". Le prénom étant passé comme paramètre dans le constructeur.
Nous allons créer aussi un objet presque vide que vous pourrez utiliser pour jouer avec le tuto.
Etape n°1 : Créons un webform avec .net 3.5 standard
Créons un simple webform "CastleWindsorExample" avec le même nom pour la solution.
Puis ajoutons un bouton et un label


Etape n°2 : Créons nos interfaces et implémentations.
Créons un nouveau projet class par exemple ClassLibrary1 (nom par défaut). Affacer le fichier ClassLibrary1.cs.
Puis créons un répertoire Interfaces. Les interfaces sont des déclarations ou on ne déclare que les points d'entrées et de sorties des méthodes de sa classe interface. Le véritable code sera à taper dans l'implémentation.
Dans le dossier interface créons une nouvelle interface (depuis le template) avec comme nom de fichier IDependency.cs
Puis tapons le code suivant. :
using System;
using System.Collections.Generic;
using System.Text;
namespace ClassLibrary1
{
public interface IDependency1
{
object SomeObject { get; set; }
}
}
Puis créons un dossier dans le répertoire root de notre classe ClassLibrary1 appelé implémentations ou business (comme vous voulez). Et créons une class avec comme nom de fichier Dependency1.cs contenant le code suivant héritant de l'interface. C'est dans cette partie qu'on se doit de créer son code.
using System;
using System.Collections.Generic;
using System.Text;
namespace ClassLibrary1
{
public class Dependency1 : IDependency1
{
public object SomeObject { get; set; }
}
}
Etape n°3 : Créons notre classe main
Dans ce cas on parle de la classe main, mais il s'agit en fait de notre classe métier maitre. C'est elle qui sera invoqué par l'interface utilisateur, puis elle chargera les bons composants pour les faire fonctionner et enfin les libérera. Cette association entre une classe maitre métier, et des interfaces associés à des implémentations pour les classes plus bas niveau, ce découplage en fait est ce qu'il faut comprendre de castle.
Dans le répertoire ClassLibrary1 créons le fichier main.cs puis tapons le code suivant
using System;
using System.Collections.Generic;
using System.Text;
namespace ClassLibrary1
{
public class main
{
private IDependency1 object1;
public main(IDependency1 dependency1, string strActor)
{
object1 = dependency1;
object1.SomeObject = strActor + " says: " + "Hello World";
}
public string DoHelloWorld()
{
return (object1.SomeObject.ToString());
}
}
}
Etape n°4 : Appelons la classe main depuis le bouton de notre webform
Dans notre cas, nous allons implémenter un bouton (bon là j'avoue c'est crado) mais cela permet de comprendre mieux, et plus simplement. Donc double-cliquez sur le bouton de votre webform et tapez le code suivant.
protected void Button1_Click(object sender, EventArgs e)
{
using (var container = new WindsorContainer())
{
container.Register(Component.For(typeof(main)).ImplementedBy(typeof(main))
.Named("main")
.Parameters(Castle.MicroKernel.Registration.Parameter.ForKey("strActor").Eq("Jerome")));
container.Register(Component.For(typeof(IDependency1))
.ImplementedBy(typeof(Dependency1)).Named("dependency1"));
var mymain = container.Resolve<main>();
Label1.Text = mymain.DoHelloWorld();
}
}
Remarquez le code. On commence par instancer son container, puis on ajoute les composants de son choix, pour info faire un Resolve.
A partir de là votre projet est exécutable. POur mieux comprendre Castle jouer avec le dernier bloc de code, puis enrichissez Dependency1 et essayez de jouer avec les méthodes que vous ajouterez.
Etape n°5 : Créons un jeu de test
C'est certainement l'un des avantages clés de Castle Windsor, facilitez les tests grâce à ce découplage. Vous pouvez donc créer un test puis ajoutez le code suivant.
using ClassLibrary1;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace TestProject4
{
[TestClass()]
public class mainTest
{
private TestContext testContextInstance;
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
[TestMethod()]
public void DoHelloWorldTest()
{
IDependency1 dependency1 = new Dependency1(); // TODO: Initialize to an appropriate value
string strActor = "Jerome"; // TODO: Initialize to an appropriate value
main target = new main(dependency1, strActor); // TODO: Initialize to an appropriate value
string expected = "Jerome says: Hello World"; // TODO: Initialize to an appropriate value
string actual;
actual = target.DoHelloWorld();
Assert.AreEqual(expected, actual);
}
}
}
Conclusion
D'une certaine manière Castle Windsor force les développeurs à mieux structurer son code. Mais cela demande aussi plus de méthode. En fait tout doit partir des uses-case UML, pour avoir un découplage (ou un découpage) comme suit.
- Les méthodes "haut niveau" comme ImprimerRapport au niveau du root de son projet de classes métiers (équivalent de notre main) ou on ne fait que charger ses composants dans son container et les utiliser.
- Les interfaces pour l'ensemble des classes.
- Les implémentations de l'ensemble des classes.
Ce type de découplage réellement vertueux pourrait être fait sans Castle bien sùr. Mais Castle apporte de nombreuses fonctionnalités par encore traitées ici... Bien sur c'est une affaire de compromis. D'un côté on facilite les tests et la maintenabilité, mais au prix de ressources CPU et d'une complexité cachée qui si elle plante devient très lourde à réparer. Reste que Castle est un projet Open Source de très grande qualité, même si l'API a changé et fait que certaines méthodes sont devenus obsolètes (ce qui a le chic de m'énerver)
Amusez vous bien 
Téléchargement du tuto
Pour télécharger le source exemple cliquez ici
Liens relatifs Windsor Castle C# :