2016-07-24 18 views
6

Czy Angular wstrzyknie więcej niż jedną instancję ogólnej usługi, jeśli jest ona wywoływana przez konstruktorów komponentów przy użyciu różnych typów?Wstrzyknięcie generycznych usług w Angular

Mam wiele usług, które będą zapewniać taką samą funkcjonalność dla różnych klas, które wszystkie dziedziczą z tej samej klasy bazowej. Chciałbym użyć ogólnego wzorca Typescript, aby poradzić sobie z tym.

Ale ja nie wiem, jak to jives z kątowym za wtryskiwacza:

  1. Czy kątowa wtryskiwacz tworzyć więcej niż jednej instancji tej usługi, jeśli jest wstrzykiwany do różnych elementów z różnych rodzajów?
  2. Czy wtryskiwacz wstrzyknie to samo wystąpienie, jeśli zostanie wywołany z tego samego typu?

Kod:

@Injectable 
export class MyService<T> { 
    ... 
} 

@Component 
export class ComponentA { 
    constructor(alphaService MyService<Alpha>) {} <--Instance 1 
} 

@Component 
export class ComponentB { 
    constructor(betaService MyService<Beta>) {} <----Instance 2? 
} 

@Component 
export class ComponentA1 { 
    constructor(alphaService MyService<Alpha>) {} <---Instance 1? 
} 

Czy to legalne? Czy wtryskiwacz wie, że tworzy dwa wystąpienia MyService?

Odpowiedz

2

Dodatkowa instancja nie zostanie utworzona dla generycznych. Jak stwierdzono here, reflect-metadata (który jest wykorzystywany przez dekoratorów kątowe 2 wspieranie typ maszynopis adnotacje) nie można uzyskać tego rodzaju informacje:

maszynopis emituje jedynie metadane typu dla typów dostępnych w czasie wykonywania, a nie nie wysyłają aliasów typu, interfejsów ani generycznych (ponieważ nie mają reprezentacji JavaScript).

Ilość MyService przypadkach zależy od tego, czy MyService zdefiniowano jako dostawcy składnika albo zostało odziedziczone macierzystego wtryskiwacza.

W powyższym kodzie, ComponentA i ComponentA1 może dziedziczyć MyService dostawcę z macierzystej wtryskiwacza, ComponentB może dostać nową instancję providers: [MyService].

9

Jest to proste rozwiązanie:

// service and models 
export class User{ 
    firstName:string 
} 
export class Admin{ 
    lastName:string 
} 

@Injectable() 
export class GenericService<T>{ 
    item:number = Math.random(); 
    GetAll():Array<T> { 
     let output = []; 
     console.log(this.item); // each instance has own value 
     return output; 
    } 
} 

Następnie ustaw swoją usługę w module poprzez useFactory:

providers: [ 
     {provide:'UserService', useFactory:()=>(new GenericService<User>())}, 
     {provide:'AdminService', useFactory:()=>(new GenericService<Admin>())}, 
    ], 

i wstrzyknąć swoje usługi z @Inject dekoratora:

constructor(@Inject('UserService') private userService:GenericService<User>, 
       @Inject('AdminService') private adminService:GenericService<Admin> 
    ) { } 

Zachowaj na uwadze, lepiej jest użyć InjectionToken (OpaqueToken jest przestarzała) dla twojego p token rovider. Użyłem napisu tylko dla uproszczenia.

+3

Uwaga: 'OpaqueToken' jest przestarzałe. Zamiast tego użyj [** 'InjectionToken' **] (https://angular.io/docs/ts/latest/api/core/index/InjectionToken-class.html). – developer033

+0

Jak więc wstrzyknąć obiekt 'HttpClient' (lub' HttpModule') dla konstruktora takiego jak ten 'konstruktor (prywatny http: HttpClient)' – Bellash

Powiązane problemy