Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Aurélien GALTIER

The dark world of .Net

Ninject : un framework de Ninja

Ninject est une framework d'injections de dépendances, d'IOC, … Lorsque l'on commence avec Ninject on en découvre un petit framework rapide à prendre en main et très limité. Mais il est loin d'être limité.

Ninja framework
Tous les exemples et tests unitaires de Ninject sont faits sur le thème des ninjas, voilà pourquoi Ninject  a un logo Ninja. http://www.ninject.org/
La version 3.0 vient de sortir il y a peu de temps. C'est un framework Open source et disponible sur Nuget. 
Beaucoup de versions disponibles :
.NET 3.5/4/4.5
SL 2/3/4/5
WP 7/7.1
Mono 2/4
Compact Framework 3.5
Et prochainement une version pour Windows 8 Metro apps.

Des intégrations dans différents type de projets WCF, MVC, WF, ...

Un kernel pour les gouverner tous
Au contraire de beaucoup de frameworks de ce type, vous n'aurez pas besoin de créer un fichier XML pour utiliser Ninject qui marche par une API fluent.

Dans Ninject la notion principale est le Kernel. Ce kernel va permettre de définir l'ensemble des éléments à intégrer dans le contexte. En général un StandarKernel suffira. Dans certains cas très spécifiques on pourra créer sa propre class Kernel. Mais vous verrez en l'utilisant qu'un StandardKernel répond déjà à beaucoup de choses.

// Création d'un kernel.
var kernel = new StandardKernel();
// Ajout de la class ProductDao dans notre contexte.
kernel.Bind<ProductDao>().ToSelf();
// on récupère une nouvelle instance de ProductDao
var productDaoInstance = kernel.Get<ProductDao>();
foreach (var product in productDaoInstance.GetProducts())
{
    Console.WriteLine(product.Title);
}

La méthode Bind permet d'indiquer quel type on va demander via la méthode Get. Puis on appelle ToSelf pour dire que l'on renverra un objet du même type. La méthode bind non générique prenant un Type en paramètre existe, ainsi on peut aussi faire des généralités.
Pour plus de souplesse je souhaiterais faire la même chose mais ne passer qu'une interface au Get. Il me suffit de faire un Bind sur une interface et de faire autre chose qu'un ToSelf. Par exemple :

// Ajout de la class ProductDao dans notre contexte.
kernel.Bind<IProductDao>().To<ProductDao>();
//On récupère une nouvelle instance de ProductDao
var productDaoInstance = kernel.Get<IProductDao>();

Maintenant on vient de créer une liaison entre l'interface IProductDao et la classe ProductDao. Cette liaison est créé à l'exécution et peut être changée dans différents cas entre autre dans les tests unitaires.
Maintenant Get<IProductDao>() me renvoit une instance de type ProductDao.

Une autre façon de faire aurait pu être d'utilisée ".ToMethod(a => new ProductDao())" ainsi vous pouvez faire ce que vous voulez au moment de la création de l'objet.

Convention
Ce que j'aime bien dans les applications c'est le développement par convention. C'est-à dire respecter des conventions d'écriture de nommage pour que l'application fonctionne correctement. Vous gagnez sur 2 points :
    - Le premier point, vous obligez l'ensemble des développeurs à faire du code le plus similaire possible.
    - Le deuxième point est la généralisation de certains fonctionnements de votre application.

On imagine bien que dans un gros projet faire un bind de chaque interface avec leurs classes pour les DAO peut être long et contraignant. Avec d'autres frameworks on fait cela dans un fichier XML mais cela est aussi très contraignant. Pour ma part il m'arrive souvent dans ces cas là d'oublier de le référencer dans le fichier XML.

Ninject est un framework très extensible il y a des packages qui existent déjà tel que Ninject.Extensions.Conventions. Utilisez Nuget pour l'installer. Dans le StandardKernel par défaut il y a un chargement automatique des modules contenus dans des assemblies Ninject.Extensions.*.dll ainsi l'extension Conventions est automatiquement opérationnelle.

Maintenant on peut écrire cela :

using Ninject.Extensions.Conventions;
            // Ajout des class *Dao dans notre contexte.
            kernel.Bind(c => c
                .FromThisAssembly()
                .SelectAllClasses()
                .EndingWith("Dao")
                .BindDefaultInterface());

Ne pas oublier de rajouter le namespace Ninject.Extentions.Conventions car si non cela ne compile pas. Ce namespace nous rajoute une méthode d'extension Bind pour les conventions.
Cette méthode Bind accepte une lambda qui passe en paramètre un objet implémentant IFromSyntax. Cette interface permet de décrire des conventions de binding dans le kernel.

.FromThisAssembly() va indiquer que l'on va travailler dans l'assembly courante. D'autres méthodes vous permettent  d'indiquer d'autres assembly.
.SelectAllClasses() on récupère toutes les classes de l'assembly courante.
.EndingWith("Dao") les noms des classes doivent terminer par le mot Dao.
.BindDefaultInterface() va binder les interfaces I*Dao avec les classes *Dao.

Il existe différentes méthodes de binding en convention. 
    - BindAllInterfaces : Qui bind toutes les interfaces de la classe avec la classe.
Equivalent :

kernel.Bind<IInterface1>().To<Class1>())
kernel.Bind<IInterface2>().To<Class1>())
kernel.Bind<IInterface3>().To<Class1>())

Si Class1 implémente les 3 interfaces.

    - BindDefaultInterface : Qui bind l'interface portant un nom similaire avec la classe.
Equivalent :

Kernel.Bind<IClass1>().To<Class1>()
Kernel.Bind<IClass2>().To<Class2>()

    - BindSingleInterface : Qui bind la seule interface existant sur le type avec la classe existante.
    - … Et bien d'autres manières où vous pourrez même créer vos propres mécaniques de Binding avec la méthode Bindwith<>

Dans mon cas l'écriture du binding est un peu plus complexe qu'avant. Mais il faut voir que demain il me suffira d'ajouter une interface et une classe qui porte un nom similaire et qui termine par Dao pour que automatiquement mon application ajoute ce DAO dans le contexte.

Conclusion
Cette article n'est qu'un début dans un prochain article on ira un peu plus loin dans l'utilisation de Ninject avec de l'injection, AOP, et des modules. Au premier abord le framework est très simple. Mais il est aussi très puissant. J'ai poussé le framework dans plein de cas, à chaque fois j'ai trouvé une solution. Au contraire de la première impression, ce framework est très flexible et je n'ai pas encore trouvé de limitation.

kernel.Bind<EndUtility>().ToSelf();
kernel.Get<EndUtility>().Bye();
Source
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: mardi 1 mai 2012 23:17 par agaltier
Classé sous : ,

Commentaires

Pas de commentaires

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01