为什么在这个 angular2 示例中我仍然需要 @inject?

Why do I still need @inject in this angular2 example?

这可能是一个特殊情况(注入浏览器本机 window 对象),但是我还是有点困惑为什么我仍然需要 @Inject() 参数装饰器 class 已经有一个 @Injectable() 装饰器。

举个简单的例子:

import { provide, bootstrap, Injectable, Inject } from '@angular/core';


@Injectable()
export class Token {
  private token: string;

  public constructor(token: string, window: Window) {
    this.token = window.atob(token);
  };

  public getToken(): string {
    return this.token;
  }
}


@Injectable()
export class TokenFactory {
  private window: Window;

  public constructor(window: Window) {
    this.window = window;
  }

  public createToken(token: string): Token {
    return new Token(token, this.window);
  }
}


@Component({
  template:   `
    <p *ngFor="let token of tokens">
      Encoded: {{token.getToken()}}
    </p>
  `,
  providers:  [ TokenFactory ]
})
class MainComponent {
  public tokens: Token[];

  public constructor(factory: TokenFactory) {
    this.tokens = [
      factory.create('token-1'),
      factory.create('token-2')
    ];
  };
}


bootstrap(
  MainComponent, [
    provide(Window, { useValue: window })
]);

概述: 我们有一个令牌 class 表示一个对象,该对象可以在一个组件或另一个服务中多次存在(因此没有单例)。令牌 class 取决于全局 window 对象(例如,用于 base64 编码)。 为了使其可测试,我们在 bootstrap 期间为全局 window object 定义了一个应用范围的提供程序,而不是直接在令牌服务中使用它。

主要组件需要动态创建令牌,因此我们创建并注入一个简单的工厂服务 TokenFactory,它还需要 window 提供程序(将其传递给构建期间的代币 class)。

问题:在浏览器中执行时失败并出现错误

Can't resolve all parameters for TokenFactory: (?).

但可以通过向工厂构造函数添加 @Inject(Window) 装饰器来修复 window 参数。

现在,我有点困惑,因为大多数 guides/tutorials 解释说在使用 Injectable 装饰器装饰 class 时,打字稿中不需要 inject 装饰器,所以为什么不使用 @Inject() decorator?

示例会失败

Config: emitDecoratorMetadataexperimentalDecorators 设置已启用,我正在使用 tsc 1.8.10angular2 rc.3.


PS: 我也愿意接受一般设计改进。

(例如,在生产场景中,我可能只会导出 Token 接口,而不是整个 class)

我不清楚问题到底是什么,但是

如果没有 @Inject(...)

type string 对于可注入的构造函数参数没有任何意义

@Injectable()
export class Token {
  private token: string;

  public constructor(token: string, window: Window) { // <<== invalid
    this.token = window.atob(token);
  };

  public getToken(): string {
    return this.token;
  }
}

但是因为你正在使用它

new Token(token, this.window);

似乎只有 @Injectable() 应该从此 class 中删除。


关于错误消息:似乎 Window 未正确导入或者它不是类型而是 OpaqueTokenstring.

如果依赖注入应该使用与参数类型不同的键,则需要

@Inject()。在您的情况下,它看起来 Window 不是一种类型 (class),因此在这样使用时不起作用。