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).

  1. Du trenger å
  • legg til @Injectable() i MyClass og
  • oppgi MyClass som providers: [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).

  1. 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

  1. 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
}

Relaterte artikler