Énoncé du problème
J'apprends Angular 4 et je suis tombé sur un code où @Inject
est utilisé dans un constructor
et je n'arrive pas à comprendre pourquoi ...
Code et source
J'utilise Angular 4 Material
Source du code:https://material.angular.io/components/dialog/overview
Dans le code, ils injectent MAT_DIALOG_DATA
constructor(public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
@Inject(MAT_DIALOG_DATA) public data: any
) { }
Quelqu'un peut-il expliquer ce que cela signifie et quand/où devrions-nous le faire?
@Inject()
est un mécanisme manuel permettant à Angular de savoir qu'un Le paramètre doit être injecté.import { Component, Inject } from '@angular/core'; import { ChatWidget } from '../components/chat-widget'; @Component({ selector: 'app-root', template: `Encryption: {{ encryption }}` }) export class AppComponent { encryption = this.chatWidget.chatSocket.encryption; constructor(@Inject(ChatWidget) private chatWidget) { } }
Dans ce qui précède, nous avons demandé que
chatWidget
soit le singleton Angular associé auclass
symboleChatWidget
en appelant@Inject(ChatWidget)
. Il est important de noter que nous utilisonsChatWidget
pour ses typages et comme référence à son singleton. Nous n'utilisons pasChatWidget
pour instancier quoi que ce soit, Angular le fait pour nous en coulisses
De https://angular-2-training-book.rangle.io/handout/di/angular2/inject_and_injectable.html
Si MAT_DIALOG_DATA
est une dépendance non-usine/classe (comme string
pour vos configurations), vous utilisez généralement @Inject
.
Vérifiez également InjectionToken
: https://angular.io/guide/dependency-injection#injectiontoken
Une solution pour choisir un jeton de fournisseur pour les dépendances non-classe consiste à définir et à utiliser un
InjectionToken
Voici un plunker: http://plnkr.co/edit/GAsVdGfeRpASiBEy66Pu?p=preview
si vous supprimez @Inject
dans ces cas, vous recevrez un
Impossible de résoudre tous les paramètres de ComponentName: (?)
Conteneur IoC dans Angular utilise les déclarations de type dans le constructeur pour déterminer les objets à injecter dans les paramètres du constructeur.
Dans votre exemple, le paramètre "public data: any
" N'a pas pu être déterminé par sa déclaration de type car il est défini comme "any". Pour résoudre ce problème, vous devez utiliser le décorateur "@Inject(MAT_DIALOG_DATA)
" pour informer le conteneur IoC de l'objet qui doit être injecté dans le paramètre "data
".
Dans votre exemple également, le décorateur "@Inject
" Est utilisé avec un InjectionToken
pour compliquer un peu les choses :)
Un InjectionToken
est en fait une classe qui est utilisée pour nommer les objets à utiliser par le conteneur IoC pour injecter dans d'autres classes. Normalement, vous pouvez utiliser n'importe quel nom de classe comme jeton pour l'injection IoC (comme "MatDialogRef<DialogOverviewExampleDialog>
" Dans votre exemple) et cela fonctionne très bien. Mais lorsque vous commencez à écrire vos UnitTests, vous vous rendez compte que vous devez utiliser des objets Mock au lieu d'objets réels à injecter dans vos classes et lorsque vous utilisez de vrais noms de classe comme jetons, vous ne pouvez pas le faire.
Pour résoudre ce problème, vous pouvez utiliser Interfaces
comme noms de jeton et c'est en fait la bonne solution, mais comme JavaScript ne prend pas en charge les interfaces, vous ne pouvez pas utiliser Interface
noms comme jetons, car le code transpilé ne contiennent Interface
définitions.
À la suite de tout cela, vous devez utiliser InjectionToken
. Un InjectionToken
vous permet d'injecter n'importe quel objet dans votre constructeur. Il vous suffit de le déclarer dans vos modules et de le mapper sur la classe réelle que vous souhaitez injecter. De cette façon, vous pouvez utiliser différentes classes pour vos codes de production et de test.