Angular 2.0 DI 我可以依赖抽象吗?

Angular 2.0 DI can I depend upon abstractions?

我一直在阅读 Angular 2.0 docs about dependency inversion and I've been looking also at some online examples

我的理解是 @injectable 装饰器使用带有 emitDecoratorMetadata 标志的 TypeScript 编译器来创建用于解析依赖项的元数据。以下面的例子 class:

TypeScript 编译器使用 emitDecoratorMetadata 通过元数据声明 DataService class 具有类型为 Http.

的构造函数参数

一旦我们使用 @Injectable 声明了 class 的依赖项,我们就可以使用 [=18= 中的 Provides 选项指示它需要被注入到某些组件中] 或 @Component 个装饰器。

我知道 emitDecoratorMetadata 的行为并且我知道它不能为接口发出元数据。因此,我假设我不能依赖 IHttp 而不是 Http:

我的假设正确吗?我可以依赖 “Depend upon Abstractions. Do not depend upon concretions.” 还是目前不可能的事情?我认为一旦 emitDecoratorMetadata 能够序列化接口,这个问题就会得到解决。

目前您需要一个类型、一个字符串名称或一个 OpaqueToken 作为提供商的键。
不支持接口,因为信息在运行时不可用。如果添加了这个,我相信 DI 会支持它们(它已经在 Dart 中得到支持)。

如果您使用的是 TypeScript,我可以为您提供解决方案。

我没有使用 Angular 2.0,但我们开发了类似的 DI 库 (intakejs)。问题是 TS 编译器仅为 classes 发出反射元数据,而不是为接口发出反射元数据(它们被视为 "object")。

希望他们能进一步添加此类功能,但现在我们正在使用基于 TypeScript 的 declaration merging 功能的 hack。这个想法是您可以声明接口,并将其与字符串或其他一些运行时 ID 合并,如下所示:

export interface IMyInjectable {
    foo(): string;
}
export const IMyInjectable = 'MyInjectable';

假设您已经实现了该接口:

@Injectable('MyInjectable')
class MyInjectable implements IMyInjectable {
    foo(): string { return 'hello' }
}

然后你可以依赖你的消费者的抽象class:

class MyConsumer {

    @Inject(IMyInjectable)
    private myInjectable: IMyInjectable;

}

希望这个小技巧能解决你的问题。