将 class 绑定到接口
Binding a class to an interface
使用打字稿,我可以轻松地将 classes 绑定到它们自己:
bootstrap(MyAppComponent, [MyClass]);
但是,我想将我的 class 绑定到一个接口,例如:
boostrap(MyAppComponent, [???]);
这样我就可以按如下方式注入它:
class MyAppComponent {
constructor(my_class : IMyClass){
}
};
这在 Angular2 中可行吗?如果是,我必须如何指定绑定?
简而言之,问题是编译打字稿时接口消失了。所以你必须将@Inject 与字符串一起使用。
或者还有另一种选择,如果您选中 the last article of Victor Savkin ,您可以在评论中找到它:
Some background. In TypeScript, interfaces are structural and are not retained at runtime. So you have to use ILoginService as follows:
constructor(@Inject("ILoginService") s:ILoginService).
You don't have to use a string - any object can be passed in there. We actually provide an object called OpaqueToken that can be used for this purpose.
interface ILoginService { login(credentials);}
const ILoginService = new OpaqueToken("LoginService");
can be used like this:
constructor(@Inject(ILoginService) s:ILoginService).
我不知道接口是否可行,因为接口在运行时不可用(javascript 不知道接口)。
但是可以使用 abstract classes.
来完成
//抽象-父-service.ts
export class DatabaseService{
getService: ()=>string;
}
//休眠。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());
}
}
But the problem with this implementation is HibernateService and
JDBCService are not able to extend any other class now because they
have already got married with 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,请确保您的子 class 服务将来不会扩展任何其他功能。
使用打字稿,我可以轻松地将 classes 绑定到它们自己:
bootstrap(MyAppComponent, [MyClass]);
但是,我想将我的 class 绑定到一个接口,例如:
boostrap(MyAppComponent, [???]);
这样我就可以按如下方式注入它:
class MyAppComponent {
constructor(my_class : IMyClass){
}
};
这在 Angular2 中可行吗?如果是,我必须如何指定绑定?
简而言之,问题是编译打字稿时接口消失了。所以你必须将@Inject 与字符串一起使用。
或者还有另一种选择,如果您选中 the last article of Victor Savkin ,您可以在评论中找到它:
Some background. In TypeScript, interfaces are structural and are not retained at runtime. So you have to use ILoginService as follows:
constructor(@Inject("ILoginService") s:ILoginService).
You don't have to use a string - any object can be passed in there. We actually provide an object called OpaqueToken that can be used for this purpose.
interface ILoginService { login(credentials);}
const ILoginService = new OpaqueToken("LoginService");
can be used like this:
constructor(@Inject(ILoginService) s:ILoginService).
我不知道接口是否可行,因为接口在运行时不可用(javascript 不知道接口)。 但是可以使用 abstract classes.
来完成//抽象-父-service.ts
export class DatabaseService{
getService: ()=>string;
}
//休眠。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());
}
}
But the problem with this implementation is HibernateService and JDBCService are not able to extend any other class now because they have already got married with 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,请确保您的子 class 服务将来不会扩展任何其他功能。