angular - Cum să injectezi serviciul într-o clasă (nu într-un component)
Aș dori să injectez un serviciu într-o clasă care nu este un component.
De exemplu:
ServiciulMeu
import {Injectable} from '@angular/core';
@Injectable()
export class myService {
dosomething() {
// implementation
}
}
ClasaMea
import { myService } from './myService'
export class MyClass {
constructor(private myservice:myService) {
}
test() {
this.myservice.dosomething();
}
}
Am încercat și nu funcționează. Se pare că serviciul trebuie folosit doar într-un component sau serviciu.
Există o modalitate de a folosi un serviciu într-o clasă normală? Sau este o practică proastă să folosești un serviciu într-o clasă normală.
Mulțumesc.
Răspuns #1
Injecțiile funcționează doar cu clase care sunt instantiate de sistemul de injecție a dependențelor (DI) al Angular.
- Trebuie să
- adaugă
@Injectable()laMyClassși - oferiți
MyClasscaproviders: [MyClass]într-un component sau NgModule.
Când injectezi apoi MyClass undeva, o instanță MyService este transmisă către MyClass atunci când este instanțiată de DI (înainte de a fi injectată pentru prima dată).
- O abordare alternativă este să configurezi un injector personalizat precum
Cu noul injector static
constructor(private injector:Injector) {
let childInjector = Injector.create({ providers: [MyClass], parent: this.injector});
let myClass : MyClass = childInjector.get(MyClass);
}
Cu ReflectiveInjector învechit
constructor(private injector:Injector) {
let resolvedProviders = ReflectiveInjector.resolve([MyClass]);
let childInjector = ReflectiveInjector.fromResolvedProviders(resolvedProviders, this.injector);
let myClass : MyClass = childInjector.get(MyClass);
}
În acest fel, myClass va fi o instanță MyClass, instanțiată de DI-ul Angular, iar myService va fi injectat în MyClass atunci când este instanțiat.
Vezi și Obținerea dependenței din Injector manual în interiorul unei directive
- Încă o modalitate este să creezi instanța tu însuți:
constructor(ms:myService)
let myClass = new MyClass(ms);
Răspunsul #2
Nu este un răspuns direct la întrebare, dar dacă citești acest SO din motivul pentru care o fac și eu, asta ar putea ajuta...
Să zicem că folosești ng2-translate și chiar vrei ca clasa ta User.ts să îl aibă. Gândul tău imediat este să folosești DI pentru a-l introduce, căci faci Angular până la urmă. Dar asta e cam mult de gândit, poți pur și simplu să-l treci în constructor, sau să-l faci o variabilă publică pe care o setezi din componentă (unde, presupun, ai folosit DI).
de exemplu:
import { TranslateService } from "ng2-translate";
export class User {
public translateService: TranslateService; // will set from components.
// a bunch of awesome User methods
}
apoi dintr-un anumit component legat de utilizator care a injectat TranslateService
addEmptyUser() {
let emptyUser = new User("", "");
emptyUser.translateService = this.translateService;
this.users.push(emptyUser);
}
Sper că acest lucru îi ajută pe cei de acolo ca mine, care erau pe punctul de a scrie mult cod mai greu de întreținut pentru că uneori suntem prea isteți =]
(NOTĂ: motivul pentru care ați putea dori să setați o variabilă în loc să o faceți parte a metodei constructor este că ați putea avea cazuri în care nu este necesar să utilizați serviciul, așa că a fi întotdeauna obligat să îl transmiteți ar însemna introducerea de importuri/cod suplimentare care nu sunt niciodată folosite cu adevărat)
Răspunsul #3
Acesta este un fel de (foarte) improvizat, dar m-am gândit să îmi împărtășesc și eu soluția. Rețineți că acest lucru va funcționa doar cu serviciile Singleton (injectate la rădăcina aplicației, nu la componentă!), deoarece ele există cât timp există aplicația ta și există întotdeauna o singură instanță a acestora.
Mai întâi, în serviciul dumneavoastră:
@Injectable()
export class MyService {
static instance: MyService;
constructor() {
MyService.instance = this;
}
doSomething() {
console.log("something!");
}
}
Apoi, în orice clasă:
export class MyClass {
constructor() {
MyService.instance.doSomething();
}
}
Această soluție este bună dacă vrei să reduci aglomerația de cod și oricum nu folosești servicii non-singleton.
Răspunsul #4
locator.service.ts
import {Injector} from "@angular/core";
export class ServiceLocator {
static injector: Injector;
}
app.module.ts
@NgModule({ ... })
export class AppModule {
constructor(private injector: Injector) {
ServiceLocator.injector = injector;
}
}
poney.model.ts
export class Poney {
id: number;
name: string;
color: 'black' | 'white' | 'brown';
service: PoneyService = ServiceLocator.injector.get(PoneyService); // <--- HERE !!!
// PoneyService is @injectable and registered in app.module.ts
}
