【问题标题】:Injection of Generic Services in Angular在 Angular 中注入通用服务
【发布时间】:2016-11-28 02:05:02
【问题描述】:

如果在使用不同类型的组件构造函数中调用通用服务,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?
}

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

【问题讨论】:

    标签: angular


    【解决方案1】:

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

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

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

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

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

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

    请记住,最好使用InjectionTokenOpaqueToken 已弃用)作为您的提供者令牌。为了简单起见,我使用了字符串。

    【讨论】:

    • 请注意:OpaqueToken 已弃用。请改用InjectionToken
    • 那么,你如何注入HttpClient(或HttpModule)这样的构造函数对象constructor(private http:HttpClient)
    • 使用@Inject("UserService") private userService: any。如果构建 GenericService 和所有 Typed 实现需要大量工作。就我而言,我需要有几十个 Typed 类才能开始我们的升级。所以我只是将 userService 视为 any,以便注入任何类型的 angularJS 服务。
    • class UserService extends GenericService&lt;User&gt; 怎么样?因为 UserService 是一个实际的类,它可以单独注入,对吧?
    【解决方案2】:

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

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

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

    在上面的代码中,ComponentAComponentA1 可以从父级注入器继承MyService 提供者,ComponentB 可以通过providers: [MyService] 获得一个新的实例。

    【讨论】:

      猜你喜欢
      • 2020-12-21
      • 2014-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-24
      • 2018-06-18
      • 1970-01-01
      • 2016-12-09
      相关资源
      最近更新 更多