129 votes

Obtenir de l'instance de service sans constructeur injection

J'ai un @Injectable de service définis dans le bootstrap. Je veux obtenir de l'instance du service sans l'aide de constructeur d'injection. J'ai essayé d'utiliser ReflectiveInjector.resolveAndCreate , mais qui semblent pour créer une nouvelle instance.

La raison pour laquelle je suis en train de faire est que j'ai un composant de base dérivée par de nombreux composants. Maintenant, j'ai besoin d'accéder à un service, mais je ne veux pas ajouter à la ctor parce que je ne veux pas injecter le service sur l'ensemble de l'instrument dérivé des composants.

TLDR: j'ai besoin d'un ServiceLocator.GetInstance<T>()

Mise à JOUR: mise à Jour du code pour RC5+: le Stockage de l'injecteur exemple pour une utilisation dans des composants

117voto

Elias Rezer Points 161

Dans la mise à jour Angulaire où 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;
  }
}

97voto

Günter Zöchbauer Points 21340

Oui, ReflectiveInjector.resolveAndCreate() crée une nouvelle et indépendante de l'injecteur instance.

Vous pouvez injecter Angulars Injector instance et d'obtenir l'instance souhaitée à partir de l'utiliser

constructor(private injector:Injector) {
  injector.get(MyService);
}

Vous pouvez également stocker l' Injector dans certains variable globale et que l'utilisation de cet injecteur exemple à acquérir fournis cas par exemple comme expliqué dans https://github.com/angular/angular/issues/4112#issuecomment-153811572

6voto

thierry templier Points 998

Une autre approche pourrait consister à définir une coutume décorateur (un CustomInjectable pour définir les métadonnées pour l'injection de dépendances:

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 mettra à profit les métadonnées à partir du constructeur parent au lieu de sa propre. Vous pouvez l'utiliser sur les enfants de la classe:

@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:

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X