Injection de dépendances #2

Cet article est une suite au précédent sur les injections de dépendances.

Pour utiliser le Container et le ServiceLocator les unités Spring.Container et Spring.Services sont nécessaire dans la liste des uses. Le container doit être construit au début du programme, dans le fichier .dpr du projet.

GlobalContainer.Build;

Exemple

En reprenant l’exemple de l’article #1 et en ajoutant deux nouveaux types de légumes.

type
  ILegume = interface
  ['{3B356366-27C9-4C4E-BF6D-FAF449D3F8C6}']
    function GetNom: string;
  end;
 
  TCarotte = class(TInterfacedObject, ILegume)
    function GetNom: string;
  end;
 
  THaricot = class(TInterfacedObject, ILegume)
    function GetNom: string;
  end;

Le CONTAINER

Une fois celui-ci créé il est possible d’enregistrer les différents types. Cela se passe dans la partie initialization de l’unité. Pour l’instant seule la carotte est enregistrée.

initialization
  GlobalContainer.RegisterType<TCarotte>.Implements<ILegume>;

Cela signifie qu’une instance de TCarotte sera donnée par le service quand un ILegume sera demandé.

Le ServiceLocator

Le ServieLocator permet de s’affranchir du Create des classes. C’est lui qui est chargé de retourner ce qui est nécessaire. Pour remplir le panier il va nous retourner une carotte.

procedure RemplirPanier;
var
  Personne: TPersonne;
  Carotte: ILegume;
begin
  Personne := TPersonne.Create(TPanier.Create);
  try
    Carotte := ServiceLocator.GetService<ILegume>;
    Personne.AjouterDansPanier(Carotte);
  finally
    Personne.Free;
  end;
end;

Lors de l’exécution on peut constater qu’il s’agit bien d’une carotte.

Déclarations multiples

Il est possible de déclarer plusieurs types pour une même interface, dans ce cas la notion de valeur par défaut est nécessaire.

initialization
  GlobalContainer.RegisterType<TCarotte>.Implements<ILegume>('Carotte');
  GlobalContainer.RegisterType<THaricot>.Implements<ILegume>('Haricot').AsDefault;

Si le code précédent est ré-exécuté le légume est désormais un haricot.

Les injections

Rien n’empêche d’ajouter le panier dans le Container, il contient une méthode pour ajouter un légume, le InjectMethod permet de s’en charger.

initialization
  GlobalContainer.RegisterType<TPanier>.Implements<IPanier>.InjectMethod('Ajouter', ['Carotte']);
  GlobalContainer.RegisterType<TCarotte>.Implements<ILegume>('Carotte');
  GlobalContainer.RegisterType<THaricot>.Implements<ILegume>('Haricot').AsDefault;

Lors de la récupération d’un IPanier, le ServiceLocator va récupérer un TPanier et passer une carotte dans la méthode Ajouter.

Il suffit de l’appeler dans la méthode remplissage.

procedure RemplirPanier;
var
  Personne: TPersonne;
begin
  Personne := TPersonne.Create(ServiceLocator.GetService<IPanier>);
  try
    // plus de code ici
  finally
    Personne.Free;
  end;
end;

Il existe aussi le InjectConstructor, InjectField et InjectProperty. Si la méthode attend plusieurs paramètres il suffit de les séparer par des virgules dans la liste.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*