【问题标题】:Angular 2.0 DI can I depend upon abstractions?Angular 2.0 DI 我可以依赖抽象吗?
【发布时间】:2016-03-20 15:25:40
【问题描述】:

我一直在阅读关于 依赖倒置 的 Angular 2.0 docs 并且我也一直在查看一些 online examples

我的理解是@injectable 装饰器使用带有emitDecoratorMetadata 标志的TypeScript 编译器来创建用于解决依赖关系的元数据。以下面的类为例:

TypeScript 编译器使用 emitDecoratorMetadata 通过元数据声明 DataService 类具有类型为 Http 的构造函数参数。

一旦我们使用@Injectable 声明了一个类的依赖关系,我们就可以指出它需要使用@App@Component 装饰器中的Provides 选项注入到某些组件中。

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

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

【问题讨论】:

    标签: angular typescript angular2-di


    【解决方案1】:

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

    【讨论】:

    • 如果我使用字符串,我如何以及在何处将字符串映射到实际类型?
    • bootstrap() 或组件中使用provide('someName', {useClass: Http}]) 和构造函数@Inject('someName') http:IHttp,而不是仅仅向提供者添加类型
    【解决方案2】:

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

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

    希望他们会进一步添加此类功能,但现在我们正在使用基于 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 MyConsumer {
    
        @Inject(IMyInjectable)
        private myInjectable: IMyInjectable;
    
    }
    

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

    【讨论】:

    • 看起来很有趣。 Injectable 装饰器不支持 @Injectable('MyInjectable') 之类的参数,尽管 github.com/angular/angular/blob/…。有必要吗?
    • 正如我之前提到的,我从未真正使用过 Angular DI。但我可以假设,@Injectable 使用类的名称创建运行时 id,因此您可以尝试将您的接口与该名称合并。
    猜你喜欢
    • 1970-01-01
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 2016-01-13
    • 2019-12-03
    • 2011-12-12
    • 1970-01-01
    相关资源
    最近更新 更多