【发布时间】:2016-11-02 15:28:36
【问题描述】:
这可能是一种特殊情况(注入浏览器本机窗口对象),但是我有点困惑,为什么当我的类已经有一个 @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 })
]);
概述:我们有一个令牌类,它表示一个对象,该对象可以在组件或另一个服务中多次存在(因此没有单例)。令牌类取决于全局窗口对象(例如,对于 base64 编码)。 为了使其可测试,我们在引导期间为全局 window object 定义了一个应用范围的提供程序,而不是直接在令牌服务中使用它。
主要组件需要动态创建令牌,所以我们创建并注入一个简单的工厂服务TokenFactory,它也需要窗口提供者(在构建过程中将令牌类传递给它)。
问题:在出现错误的浏览器中执行时失败
Can't resolve all parameters for TokenFactory: (?).
但可以通过在工厂构造函数 window 参数中添加 @Inject(Window) 装饰器来修复。
现在,我有点困惑,因为大多数指南/教程都解释说,在使用 Injectable 装饰器装饰类时,打字稿中不需要注入装饰器,那么为什么不使用 @Inject( ) 装饰器?
配置: emitDecoratorMetadata 和 experimentalDecorators 设置已启用,我正在使用 tsc 1.8.10 和 angular2 rc.3.
PS: 我也愿意接受一般的设计改进。
(例如,在生产场景中,我可能只会导出 Token 接口而不是整个类)
【问题讨论】:
-
您能否详细介绍一下 Window 类的定义位置以及如何导入它?谢谢!
-
它的浏览器全局 window object 暴露为 window (情人案例)。它在引导期间被注入底部。嗯...,在这种情况下,provider-name 是否必须是字符串或更好的是 OpaqueToken,因为 typescript/angular 可能会混淆 Window name 属性?
-
我忘了说,这是一个运行时(浏览器)错误而不是编译时(tsc)...
标签: dependency-injection angular factory-pattern