J'ai un service @Injectable
Défini dans le bootstrap. Je veux obtenir l'instance du service sans utiliser l'injection de constructeur. J'ai essayé d'utiliser ReflectiveInjector.resolveAndCreate
Mais cela semble créer une nouvelle instance.
La raison pour laquelle j'essaie de faire est que j'ai un composant de base dérivé de nombreux composants. Maintenant, je dois accéder à un service, mais je ne veux pas l'ajouter au ctor, car je ne veux pas l'injecter sur tous les composants dérivés.
TLDR: j'ai besoin d'une ServiceLocator.GetInstance<T>()
UPDATE: Code mis à jour pour RC5 +: enregistrement d'une instance d'injecteur à utiliser dans des composants
Oui, ReflectiveInjector.resolveAndCreate()
crée une nouvelle instance d'injecteur non connectée.
Vous pouvez injecter une instance de Angulars Injector
et en obtenir l’instance souhaitée en utilisant
constructor(private injector:Injector) {
injector.get(MyService);
}
Vous pouvez également stocker Injector
dans une variable globale et utiliser cette instance d'injecteur pour acquérir les instances fournies, par exemple comme expliqué dans https://github.com/angular/angular/issues/4112# issuecomment-153811572
Dans le Angular mis à jour où les ngModules sont utilisés, vous pouvez créer une variable disponible n'importe où dans le code:
export let AppInjector: Injector;
export class AppModule {
constructor(private injector: Injector) {
AppInjector = this.injector;
}
}
Une autre approche consisterait à définir un décorateur personnalisé (un CustomInjectable
pour définir les métadonnées pour l'injection de dépendance:
export function CustomComponent(annotation: any) {
return function (target: Function) {
// DI configuration
var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
var parentAnnotations = Reflect.getMetadata('design:paramtypes', parentTarget);
Reflect.defineMetadata('design:paramtypes', parentAnnotations, target);
// Component annotations / metadata
var annotations = Reflect.getOwnMetadata('annotations', target);
annotations = annotations || [];
annotations.Push(annotation);
Reflect.defineMetadata('annotations', annotations, target);
}
}
Il utilisera les métadonnées du constructeur parent au lieu de ses propres. Vous pouvez l'utiliser sur la classe enfant:
@Injectable()
export class SomeService {
constructor(protected http:Http) {
}
}
@Component()
export class BaseComponent {
constructor(private service:SomeService) {
}
}
@CustomComponent({
(...)
})
export class TestComponent extends BaseComponent {
constructor() {
super(arguments);
}
test() {
console.log('http = '+this.http);
}
}
Voir cette question pour plus de détails: