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

Tom*_*asi 2 dependency-injection factory-pattern angular

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

举个简单的例子:

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

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

主要组件需要动态创建令牌,因此我们创建并注入一个简单的工厂服务TokenFactory,它还需要窗口提供程序(在构造期间将令牌类传递给它).

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

Can't resolve all parameters for TokenFactory: (?).
Run Code Online (Sandbox Code Playgroud)

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

现在,我有点困惑,因为大多数指南/教程解释了在使用Injectable装饰器装饰类时,typescript中不需要inject装饰器,那么为什么示例会在不使用@Inject()装饰器的情况下失败

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


PS: 我也对一般的设计改进持开放态度.

(例如.在生产场景中,我可能只导出令牌接口而不是整个类)

Gün*_*uer 5

我不清楚问题究竟是什么,但是

string如果没有注入的构造函数参数的类型没有任何意义@Inject(...)

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

但是因为你正在使用它

new Token(token, this.window);
Run Code Online (Sandbox Code Playgroud)

似乎@Injectable()应该从这个班级中删除.


关于错误消息:它看起来Window没有正确导入或它不是一个类型而是一个OpaqueToken或一个string.

@Inject()如果依赖注入应使用与参数类型不同的键,则是必需的.在你的情况下,它看起来Window不是一个类型(类),因此在使用时不起作用.

  • 好的捕获,你是对的我应该删除Token类的注入,因为_token_参数不是要注入,而是实际上更多的输入参数.你对窗口的评论敲响了钟,因为窗口_object_来自浏览器,它可能没有装饰(没有元数据),因此angular需要工厂窗口参数上的Inject docorator; 听起来不错. (3认同)