在Angular中注入通用服务

Dan*_*ick 16 angular

如果使用不同的类型跨组件构造函数调用Angular,它会注入多个通用服务的实例吗?

我有很多服务将为从同一基类继承的不同类提供相同的功能.我想使用Typescript的通用模式MyService<T extends BaseClass>来处理这个问题.

但是我不知道它是如何与Angular的注射器一起生效的:

  1. 如果将Angular注入器注入具有不同类型的不同组件,它是否会创建此服务的多个实例
  2. 如果使用相同的类型调用它,注入器是否会注入相同的实例

码:

@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?
}
Run Code Online (Sandbox Code Playgroud)

这合法吗?注射器是否知道创建两个MyService实例?

Him*_*men 20

这是一个简单的解决方案:

// 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后通过useFactory在模块中设置您的服务:

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

并使用@Inject装饰器注入您的服务:

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

请记住,最好为您的提供者令牌使用InjectionToken(不推荐使用OpaqueToken).为了简单起见,我使用了字符串.

  • 只是注意:`OpaqueToken`已被弃用.请改用[**`InjectionToken`**](https://angular.io/docs/ts/latest/api/core/index/InjectionToken-class.html). (3认同)
  • 那“类 UserService 扩展 GenericService&lt;User&gt;”呢?由于 UserService 是一个实际的类,因此可以单独注入,对吧? (3认同)
  • 那么,如何为构造函数注入“HttpClient”(或“HttpModule”)对象,例如“constructor(private http:HttpClient)” (2认同)

Est*_*ask 5

不会为泛型创建额外的实例。正如此处所述reflect-metadata(Angular 2 装饰器使用它来支持 TypeScript 类型注释)无法获得此类信息:

TypeScript 只为运行时可用的类型发出类型元数据,不发出类型别名、接口或泛型(因为它们没有 JavaScript 表示)。

MyService实例的数量取决于是MyService被定义为组件的提供者还是从父注入器继承而来。

在上面的代码中,ComponentA并且ComponentA1可以MyService从父注入器继承提供者,ComponentB可以使用providers: [MyService].