Extensions

Vous pouvez étendre le container principal et enregistrer vos propres services, requêtes et notifications.
Pour ce faire vous devez récupérer le module principal de Mainlib et utiliser la méthode bind de inversify pour enregistrer vos dépendances.
Puis vous devez créer la composition racine de la même façon que dans la section Injection de dépendances.

Faites attention aux références circulaires, notamment si vous utilisez beaucoup les imports.
      

import {inject} from "inversify";
import "reflect-metadata";
import {MainLibModule, Mediator} from "@adclz/fevermainlib/kernel";
 
const Kernel = MainLibModule()
const Kernel: Container
 

Service

Afin de déclarer un service, vous devez utiliser le décorateur @injectable() de inversify afin de déclarer ce service en tant que dépendance injectable.

      

import {inject, injectable} from "inversify";
import "reflect-metadata";
 
@injectable()
export class MyService {
constructor() {
}
}
 

Injection des services

L'injection se fait via l'utilisation de l'attribut @inject(), vous pouvez remplacer AurhService par le nom du service voulu et importer autant de services que vous le souhaitez, Inversify se chargera de vous fournir via la composition racine.

      

import {inject, injectable} from "inversify"
import "reflect-metadata"
import AuthService from "@adclz/fevermainlib/services/auth"
 
@injectable()
export default class MyService {
private readonly AuthService: AuthService
 
constructor(@inject(AuthService) AuthService: AuthService) {
this.AuthService = AuthService
}
}
 

Injection du médiateur

Le médiateur est un service à part entière, ainsi son injection ne diffère pas des autres services.

      

import {inject, injectable} from "inversify";
import "reflect-metadata";
import {Mediator} from "@adclz/fevermainlib/kernel"
 
@injectable()
export default class MyService {
private readonly Mediator: Mediator
 
constructor(@inject(Mediator) Mediator: Mediator) {
this.Mediator = Mediator
}
}
 

Kernel

Vous devez ensuite enregistrer votre servide dans lé kernel afin que celui-ci puisse l'injecter dans d'autres services. Ici le kernel retourne le service MyService en mode Singleton.

      

import {inject, injectable} from "inversify";
import "reflect-metadata";
import {
MainLibModule,
Mediator
} from "@adclz/fevermainlib/kernel";
 
@injectable()
export default class MyService {
private readonly Mediator: Mediator
 
constructor(@inject(Mediator) Mediator: Mediator) {
this.Mediator = Mediator
}
}
 
const Kernel = MainLibModule()
 
Kernel.bind<MyService>(MyService).toSelf().inSingletonScope()
 

Mediateur

Requêtes

IMediatorRequest

La création de reqûetes se fait en 2 temps.
Vous devez d'abord créer une classe qui implémente IMediatorRequest.

interface IMediatorRequest<T, Y> {
    _data: T
    _return: Y
}
  • _data indique le type de données qui doit être passé dans le constructeur de la reqûete.
  • _return indique le type de retour que IMediatorRequestHandler doit retourner.
Pourquoi utiliser _data et _return alors que les types pourraient être déduits des termes génériques de IMediatorRequest ?

Car IMediatorRequestHandler ne peut pas déduire les termes génériques dans IMediatorRequest, c'est un problème du à TypeScript.

Voir: https://github.com/Microsoft/TypeScript/issues/1213.
Du à cette contrainte vous devez rajouter ! à la fin de _return afin de forcer une assertion du type de retour, car IMediatorRequest n'est pas responsable de sa création.

IMediatorRequestHandler

IMediatorRequestHandler est la fonction qui est responsable de l'éxecution de IMediatorRequest.
La requête est passée dans la méthode Execute.

interface IMediatorRequestHandler<T extends IMediatorRequest<any, any>> {
    Execute: (Request: T) => T["_return"];
}

Exemple

Dans cet exemple, MyRequest est une reqûete qui accepte un paramètre string, la classe responsable d'éxecuter cette reqûete retourne un booléen.

      

import {injectable} from "inversify";
import "reflect-metadata";
import {
MainLibModule,
IMediatorRequest,
IMediatorRequestHandler,
Mediator
} from "@adclz/fevermainlib/kernel";
 
@injectable()
export class MyRequest implements IMediatorRequest<string, boolean> {
public readonly _data!: string;
public readonly _return!: boolean;
 
constructor(data: string) {
this._data = data
}
}
 
@injectable()
export class MyRequestHandler implements IMediatorRequestHandler<MyRequest> {
 
constructor() {
}
 
public Execute(MyRequest: MyRequest) {
console.log(MyRequest._data)
(property) MyRequest._data: string
return true
}
}
 

Vous pouvez injecter des services dans le constructeur de IMediatorRequestHandler.

Il est recommandé d'utiliser un LazyServiceIdentifier afin de mettre en place une injection tardive.
import {inject, injectable, LazyServiceIdentifier} from "inversify";
      

//...
@injectable()
export class MyRequestHandler implements IMediatorRequestHandler<MyRequest> {
private readonly Mediator: Mediator
constructor(@inject(new LazyServiceIdentifer(() => Mediator)) Mediator: Mediator) {
this.Mediator = Mediator
}
 
public Execute(MyRequest: MyRequest) {
console.log(MyRequest._data)
return true
}
}
 

Kernel

Une fois votre requête et la classe responsable de son exécution crées, vous devez les enregistrer dans le kernel.

Ici, le kernel passe en paramètre un objet IMediatorRequest à MyRequesthandler lorsque celui-ci est de nom MyRequest.

      

const Kernel = MainLibModule()
 
Kernel.bind<IMediatorRequestHandler<IMediatorRequest<any, any>>>("IMediatorRequestHandler<IMediatorRequest>")
.to(MyRequestHandler)
.whenTargetNamed("MyRequest")
 

Notification

La création d'une notification se fais via l'implémentation de la classe abstraite IMediatorNotification.

IMediatorNotification

Vous définissez le type de l'objet qui est envoyé à tous les abonnés via le terme générique de IMediatorNotification.

      

import {inject, injectable} from "inversify";
import "reflect-metadata";
import {
IMediatorNotification,
Mediator
} from "@adclz/fevermainlib/kernel";
 
@injectable()
export class OnMyNotification extends IMediatorNotification<any> {
}
 

Kernel

Ici, le kernel exécute OnMyNotification lorsque l'objet en paramètre est de nom OnMyNotification.
Les notifications doivent être enregistrés en mode Singleton.

      

import {inject, injectable} from "inversify";
import "reflect-metadata";
import {
MainLibModule,
IMediatorNotification,
Mediator
} from "@adclz/fevermainlib/kernel";
 
@injectable()
export class OnMyNotification extends IMediatorNotification<any> {
}
 
const Kernel = MainLibModule()
 
Kernel.bind<IMediatorNotification<any>>("IMediatorNotification")
.to(OnMyNotification)
.inSingletonScope()
.whenTargetNamed("OnMyNotification")