Shared Services Injection in Angular

Will Angular inject more than one instance of a shared service if it is called in Component constructors using different types?

I have many Services that will provide the same functionality for different classes that all inherit from the same base class. I would like to use Typescript general template MyService<T extends BaseClass> to handle this.

But I don't know how these jives are with an Angular injector:

  • Will an Angular injector create multiple instances of this service if it is implemented in different components with different types?
  • Will the injector inject the same instance if it is called with the same type?

the code:

 @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? } 

Is it legal? Does the injector know to create two instances of MyService?

+6
source share
2 answers

An additional instance will not be created for generics. As stated here , reflect-metadata (which is used by Angular 2 decorators to support TypeScript type annotations) cannot get this information:

TypeScript only generates type metadata for types available at runtime, and does not generate type aliases, interfaces, or generics (since they do not have JavaScript representation).

The number of MyService instances depends on whether the MyService defined as a component provider or whether it was inherited from the parent injector.

In the above code, ComponentA and ComponentA1 can inherit the MyService provider from the parent injector, ComponentB can get a new instance with providers: [MyService] .

+2
source

This is a simple solution:

 // 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; } } 

Then install your service in the module through useFactory:

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

and enter your service using the @Inject decorator:

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

Keep in mind that it is better to use an InjectionToken ( OpaqueToken is deprecated) for your token provider. I used the string just for simplicity.

+10
source

All Articles