绑定一个类到一个接口

27

使用 TypeScript,我可以轻松地将类绑定到自身:

bootstrap(MyAppComponent, [MyClass]);

然而,我想将我的类绑定到一个接口,就像这样:

boostrap(MyAppComponent, [???]);

以便我能够像以下这样注入它:

class MyAppComponent {
    constructor(my_class : IMyClass){
    }
};

在Angular2中是否有可能做到这一点?如果是,我需要如何指定绑定?

2个回答

26
简而言之,问题在于当typescript编译时,接口会消失。因此,您需要使用带有字符串的@Inject。

另外还有另一种选择,如果您查看Victor Savkin的最后一篇文章(链接),您可以在评论中找到以下内容:

一些背景信息。在TypeScript中,接口是结构性的,并且在运行时不会保留。因此,您必须按如下方式使用ILoginService:

constructor(@Inject("ILoginService") s:ILoginService).

您不必使用字符串-任何对象都可以传递。我们实际上提供了一个称为OpaqueToken的对象,可用于此目的。

interface ILoginService { login(credentials);}
const ILoginService = new OpaqueToken("LoginService");

可以像这样使用:
constructor(@Inject(ILoginService) s:ILoginService).

为什么 new OpaqueToken("LoginService") 传递的是 LoginService 而不是 ILoginService - Danny Bullis
@DannyBullis 这里没有传递 LoginService 以供使用,我们所做的是创建一个 OpaqueToken 并将其传递给我们在构造函数中请求 OpaqueToken 时要使用的值。这只是一个示例字符串。请注意,OpaqueToken 已被弃用,应使用 InjectionToken。更多了解可以在此处找到 https://dev59.com/L1gR5IYBdhLWcg3wd9K5 - hogan

8
我不知道接口是否能够实现该功能,因为在运行时(JavaScript无法识别接口)接口将不可用。但可以使用抽象类进行实现。
//abstract-parent-service.ts
export class DatabaseService{
    getService: ()=>string;
}

//hibernate.service.ts

import {DatabaseService} from "./abstract-parent-service";

export class HibernateService implements DatabaseService{
  constructor() { }
  getService() {
    return "i am hibernate";
  }
}

//jdbc.service.ts

import {DatabaseService} from "./abstract-parent-service";

export class JDBCService implements DatabaseService{
  constructor() { }
  getService() {
    return "i am Jdbc";
  }
}

//cmp-a.component.ts

import {DatabaseService} from "./abstract-parent-service";
import {HibernateService} from "./hibernate.service";

@Component({
    selector: 'cmp-a',
    template: `<h1>Hello Hibernate</h1>`,
    providers: [{provide: DatabaseService, useClass: HibernateService}]
})
export class CmpAComponent {
    constructor (private databaseService: DatabaseService) {
        console.log("Database implementation in CompA :"+this.databaseService.getService());
    }
}

//cmp-b.component.ts

import {DatabaseService} from "./abstract-parent-service";
import {HibernateService} from "./hibernate.service";

@Component({
    selector: 'cmp-b',
    template: `<h1>Hello Jdbc</h1>`,
    providers: [{provide: DatabaseService, useClass: JDBCService}]
})
export class CmpAComponent {
    constructor (private databaseService: DatabaseService) {
        console.log("Database implementation in CompA :"+this.databaseService.getService());
    }
}

但是这种实现方式存在问题,HibernateService和JDBCService现在无法继承任何其他类,因为它们已经与DatabaseService绑定在一起。
class A{
    constructor(){
        console.log("in A");
    }
}
class B extends A{
    constructor(){
        super();
        console.log("in B");
    }
}
class C extends A{
    constructor(){
        super();
        console.log("in C");
    }
}
let c = new C();

//This thing is not possible in typescript
class D extends B, C{//error:  Classes can only extend a single class
    constructor(){
        super();// which constructor B or C
        console.log("in D");
    }
}

如果您将此模式用于DI,请确保您的子类服务不会在未来扩展任何其他功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接