2016-05-27 14 views
31

Ho un servizio @Injectable definito in bootstrap. Voglio ottenere l'istanza del servizio senza utilizzare l'iniezione del costruttore. Ho provato a utilizzare ReflectiveInjector.resolveAndCreate ma sembra che crei una nuova istanza.Ottenere l'istanza di servizio senza l'iniezione del costruttore

Il motivo per cui sto provando a fare è che ho un componente di base derivato da molti componenti. Ora ho bisogno di accedere a un servizio ma non voglio aggiungerlo al Ctor perché non voglio iniettare il servizio su tutti i componenti derivati.

TLDR: Ho bisogno di un UPDATE ServiceLocator.GetInstance<T>()

: codice aggiornato per RC5 +: Storing injector instance for use in components

risposta

35

Sì, ReflectiveInjector.resolveAndCreate() crea una nuova istanza e non collegato iniettore.

È possibile iniettare Angolari Injector esempio e ottenere l'istanza desiderata utilizzando

constructor(private injector:Injector) { 
    injector.get(MyService); 
} 

È anche possibile memorizzare il Injector in qualche variabile globale e di utilizzare questa istanza iniettore per acquisire previste istanze per esempio come illustrato nel https://github.com/angular/angular/issues/4112#issuecomment-153811572

+1

Memorizzazione iniettore in un var globale iable in bootstrap.then() suona come quello che mi serve. – dstr

+8

La domanda dice senza un costruttore che rende questa risposta piuttosto inutile. –

+0

Senza il costruttore non c'è iniezione. Dovremmo eliminare la domanda quindi ;-) –

4

un altro approccio consisterebbe di definire un decoratore personalizzato (un CustomInjectable per impostare i metadati per l'iniezione di dipendenza:

export function CustomComponent(annotation: any) { 
    return function (target: Function) { 

    // DI configuration 
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor; 
    var parentAnnotations = Reflect.getMetadata('design:paramtypes', parentTarget); 

    Reflect.defineMetadata('design:paramtypes', parentAnnotations, target); 

    // Component annotations/metadata 
    var annotations = Reflect.getOwnMetadata('annotations', target); 
    annotations = annotations || []; 
    annotations.push(annotation); 
    Reflect.defineMetadata('annotations', annotations, target); 
    } 
} 

Sfrutterà i metadati del costruttore padre anziché i propri. Si può usare sulla classe bambino:

@Injectable() 
export class SomeService { 
    constructor(protected http:Http) { 
    } 
} 

@Component() 
export class BaseComponent { 
    constructor(private service:SomeService) { 
    } 
} 

@CustomComponent({ 
    (...) 
}) 
export class TestComponent extends BaseComponent { 
    constructor() { 
    super(arguments); 
    } 

    test() { 
    console.log('http = '+this.http); 
    } 
} 

Vedere questa domanda per maggiori dettagli:

+1

Il problema è tsc non mi permette di chiamare super (argomenti) perché gli argomenti per il costruttore base non corrispondono. – parliament

+1

in questo caso particolare possiamo semplicemente rimuovere il costruttore dalla classe derivata https://github.com/Microsoft/TypeScript/issues/12439 – slowkot

8

Nel angolare aggiornata in cui vengono utilizzati ngModules, è possibile creare una variabile disponibile ovunque nel codice:

export let AppInjector: Injector; 

export class AppModule { 
    constructor(private injector: Injector) { 
    AppInjector = this.injector; 
    } 
} 
+0

Nice. Potrebbe essere una buona risposta a http://stackoverflow.com/questions/39409328/storing-injector-instance-for-use-in-components pure. – Arjan

+0

Sei il re! –