将类绑定到接口

Wil*_*ert 26 dependency-injection typescript angular

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

bootstrap(MyAppComponent, [MyClass]);
Run Code Online (Sandbox Code Playgroud)

但是,我想将我的类绑定到一个接口,如下所示:

boostrap(MyAppComponent, [???]);
Run Code Online (Sandbox Code Playgroud)

这样我可以按如下方式注入:

class MyAppComponent {
    constructor(my_class : IMyClass){
    }
};
Run Code Online (Sandbox Code Playgroud)

这在Angular2中是否可行?如果是,我该如何指定绑定?

Arn*_*lin 26

简而言之,问题是编译typescript时接口消失了.所以你必须使用带字符串的@Inject.

或者还有另一种选择,如果您查看Victor Savkin的最后一篇文章,您可以在评论中找到:

一些背景.在TypeScript中,接口是结构化的,在运行时不会保留.所以你必须使用ILoginService,如下所示:

constructor(@Inject("ILoginService") s:ILoginService).
Run Code Online (Sandbox Code Playgroud)

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

interface ILoginService { login(credentials);}
const ILoginService = new OpaqueToken("LoginService");
Run Code Online (Sandbox Code Playgroud)

可以像这样使用:

constructor(@Inject(ILoginService) s:ILoginService).
Run Code Online (Sandbox Code Playgroud)


Aru*_*mar 8

我不知道是否可以使用接口,因为接口在运行时将无法使用(javascript不知道接口).但它可以使用抽象类来完成.

//abstract-parent-service.ts

export class DatabaseService{
    getService: ()=>string;
}
Run Code Online (Sandbox Code Playgroud)

//hibernate.service.ts

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

export class HibernateService implements DatabaseService{
  constructor() { }
  getService() {
    return "i am hibernate";
  }
}
Run Code Online (Sandbox Code Playgroud)

//jdbc.service.ts

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

export class JDBCService implements DatabaseService{
  constructor() { }
  getService() {
    return "i am Jdbc";
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

但是这个实现的问题是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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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