2015-08-27 12 views
22

Utilizzando dattiloscritto, posso facilmente legarsi classi a se stessi:Binding una classe a un'interfaccia

bootstrap(MyAppComponent, [MyClass]); 

Tuttavia, vorrei legare la mia classe a un'interfaccia, come ad esempio:

boostrap(MyAppComponent, [???]); 

in modo tale da poterlo iniettare nel modo seguente:

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

È possibile in Angular2? Se sì, come devo specificare l'associazione?

risposta

24

Per farla breve il problema è che le interfacce scompaiono quando viene compilato il dattiloscritto. Quindi dovresti usare @Inject con una stringa.

Oppure c'è un'altra opzione, se controlli the last article of Victor Savkin è possibile trovare questo nei commenti:

Alcuni retroscena. In TypeScript, le interfacce sono strutturali e non vengono mantenute in fase di runtime. Quindi, è necessario utilizzare ILoginService come segue:

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

Non è necessario utilizzare una stringa - qualsiasi oggetto può essere passato in là. In realtà forniamo un oggetto chiamato OpaqueToken che può essere utilizzato per questo scopo.

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

può essere utilizzato in questo modo:

constructor(@Inject(ILoginService) s:ILoginService). 
+0

perché 'il nuovo OpaqueToken (" LoginService ")' ha superato 'LoginService' e non' ILoginService'? –

6

Non so se è possibile con l'interfaccia come interfaccia non sarà disponibile in fase di esecuzione (javascript non sa di interfaccia). Ma può essere fatto usando classi astratte.

//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()); 
    } 
} 

ma il problema con questa implementazione è HibernateService e JDBCService non sono in grado di estendere qualsiasi altra classe ora perché hanno già sposati con 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"); 
    } 
} 

Se si utilizza questo modello per DI, rendere sicuro che i vostri servizi di classe bambino non stanno andando per estendere qualsiasi altra funzionalità in futuro.

Problemi correlati