developer.jelix.org n'est plus utilisée, et existe uniquement pour son historique. Postez les nouveaux tickets sur le compte github.
Version 2 (modified by doubleface, 12 years ago) (diff) |
---|
Inversion de contrôle dans Jelix
Ce document vise à expliquer l'implémentation actuelle de l'inversion de contrôle dans Jelix, dans le but permettre aux contributeurs de l'améliorer plus facilement.
Introduction
Cette implémentation (très partielle) de l'inversion de contrôle est très inspirée de celle de Stubbles qui est très intéressante à regarder en introduction à ce document. J'ai tenté d'adapter cette implémentation à Jelix mais en supprimant beaucoup de choses comme l'utilisation des annotations ou de la réflexion afin de garder de bonnes performances et aussi en mettant au centre de cette implémentation les sélecteurs de Jelix. De plus, il n'y a pour le moment pas de gestion des paramètres du constructeur.
Utilisation
jClassBinding permet, lorqu'on fait appel à une interface par l'intermédiaire de jClasses, de laisser la possibilité, par configuration, de choisir l'implémentation qui se trouve derrière cette interface et donc d'en récupérer une instance. Exemple :
$instance = jClasses::getBindedService('module~serviceItf');
Si je n'ai rien fait de spécial avant et que j'exécute ce code, je vais récupérer une exception car j'ai essayé d'instancier serviceItf qui est une interface. Donc, comment associer serviceItf à un classe bien réelle : par un autre sélecteur vers cette classe. Voici les façons, par ordre de priorité pour faire cette association :
- par un code spécifique :
jClasses::bind('module~serviceItf')->to('module~serviceClass');
- par le fichier de configuration de jelix:
[classbindings] module-serviceItf = "module~serviceClass"
Noter que a gauche du "=", "~" est remplacé par un "-" car les "~" sont interdits dans les fichiers ini pour les clés.
- par une constante spéciale dans l'interface :
interface serviceItf { const JBINDING_BINDED_IMPLEMENTATION = "module~serviceClass"; }
Si on utilise jClasses::getBindedService, l'instance associée est un sungleton alors que si on utilise jClasses::createBinded, on à chaque fois une nouvelle instance.
Il est aussi possible de lier une classe à une autre classe :
jClasses::bind('class:module~serviceClass')->to('module~serviceClassBis');
Si on essaye d'instancier la liaison d'une classe et que celle-ci n'en a pas, sa propre implémentation sera utilisée :
jClasses::getBindedService('module~classWithoutBinding'); // retourne une instance de classWithoutBinding
Il est aussi possible de lier directement une classe ou une interface à une instance. C'est très pratique en particulier encore pour les test unitaire en utilisant ceci conjointement avec les Mock Objects :
// Suppose we are in a PHPUnit test $CalledMock = $this->getMock('Called'); // We create a mock object from the called object jClasses::bind('module~CalledItf')->toInstance($CalledMock); Caller->methodToTest();
Manques
- Pas de gestion des paramètre de constructeur
- Sûrement d'autres chose (à compléter)