angular - Hvordan injisere tjeneste i klasse (ikke komponent)
Jeg vil injisere en tjeneste i en klasse som ikke er en komponent.
For eksempel:
Min tjeneste
import {Injectable} from '@angular/core';
@Injectable()
export class myService {
dosomething() {
// implementation
}
}
MinKlasse
import { myService } from './myService'
export class MyClass {
constructor(private myservice:myService) {
}
test() {
this.myservice.dosomething();
}
}
Jeg prøvde, og det fungerer ikke. Det ser ut til at tjenesten kun må brukes i komponenten eller tjenesten.
Finnes det en måte å bruke en tjeneste i en vanlig klasse på? Eller er det dårlig praksis å bruke en tjeneste i en vanlig klasse.
Takk.
Svar #1
Injeksjoner fungerer bare med klasser som blir instansiert av Angulars avhengighetsinjeksjon (DI).
- Du trenger å
- legg til
@Injectable()iMyClassog - oppgi
MyClasssomproviders: [MyClass]i en komponent eller NgModule.
Når du da injiserer MyClass et sted, blir en MyService-instans sendt til MyClass når den blir opprettet av DI (før den injiseres første gang).
- En alternativ tilnærming er å konfigurere en egendefinert injektor som
Med den nye statiske injektoren
constructor(private injector:Injector) {
let childInjector = Injector.create({ providers: [MyClass], parent: this.injector});
let myClass : MyClass = childInjector.get(MyClass);
}
Med den foreldede ReflectiveInjector
constructor(private injector:Injector) {
let resolvedProviders = ReflectiveInjector.resolve([MyClass]);
let childInjector = ReflectiveInjector.fromResolvedProviders(resolvedProviders, this.injector);
let myClass : MyClass = childInjector.get(MyClass);
}
På denne måten vil myClass være en MyClass-instans, opprettet av Angulars DI, og myService vil bli injisert i MyClass når den instansieres.
Se også Hente avhengighet fra Injector manuelt inne i en direktiv
- En annen måte er å opprette instansen selv:
constructor(ms:myService)
let myClass = new MyClass(ms);
Svar #2
Ikke et direkte svar på spørsmålet, men hvis du leser dette SO av den grunnen jeg gjør, kan dette hjelpe...
La oss si at du bruker ng2-translate og du virkelig vil at User.ts-klassen din skal ha det. Din umiddelbare tanke er å bruke DI for å putte det inn, du jobber tross alt med Angular. Men det er litt å overtenke det, du kan bare sende det inn i konstruktøren din, eller gjøre det til en offentlig variabel som du setter fra komponenten (hvor du antageligvis gjorde DI på det).
f.eks.:
import { TranslateService } from "ng2-translate";
export class User {
public translateService: TranslateService; // will set from components.
// a bunch of awesome User methods
}
deretter fra en brukerrelatert komponent som injiserte TranslateService
addEmptyUser() {
let emptyUser = new User("", "");
emptyUser.translateService = this.translateService;
this.users.push(emptyUser);
}
Forhåpentligvis hjelper dette dem der ute som meg som var i ferd med å skrive mye vanskeligere kode å vedlikeholde fordi vi noen ganger er for smarte =]
(MERK: grunnen til at du kanskje vil sette en variabel i stedet for å gjøre det til en del av konstruktørmetoden din, er at du kan ha tilfeller der du ikke trenger å bruke tjenesten, så det å alltid være nødt til å sende den inn ville bety å introdusere ekstra imports/kode som aldri egentlig brukes)
Svar #3
Dette er ganske (veldig) hackete, men jeg tenkte jeg kunne dele min løsning også. Merk at dette kun vil fungere med Singleton-tjenester (injisert i app-roten, ikke komponenten!), siden de lever så lenge som applikasjonen din, og det finnes bare én forekomst av dem.
Først, i din tjeneste:
@Injectable()
export class MyService {
static instance: MyService;
constructor() {
MyService.instance = this;
}
doSomething() {
console.log("something!");
}
}
Så i enhver klasse:
export class MyClass {
constructor() {
MyService.instance.doSomething();
}
}
Denne løsningen er god hvis du vil redusere koderot og uansett ikke bruker ikke-singleton-tjenester.
Svar #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
}
