2016-05-27 31 views
31

Mam zdefiniowaną usługę startową w usłudze @Injectable. Chcę uzyskać wystąpienie usługi bez użycia wtrysku konstruktora. Próbowałem użyć ReflectiveInjector.resolveAndCreate, ale wydaje się, że tworzymy nową instancję.Uzyskiwanie instancji usługi bez wstrzyknięcia konstruktora

Powodem, dla którego próbuję zrobić, jest to, że mam komponent bazowy wyprowadzony przez wiele komponentów. Teraz muszę uzyskać dostęp do usługi, ale nie chcę dodawać go do ctor, ponieważ nie chcę wstrzykiwać usługi na wszystkie składniki pochodne.

TLDR: Potrzebuję ServiceLocator.GetInstance<T>()

UPDATE: kod Aktualizacja dla RC5 +: Storing injector instance for use in components

Odpowiedz

35

Tak, ReflectiveInjector.resolveAndCreate() tworzy nową instancję i niezwiązanej wtryskiwacza.

można wstrzykiwać Angulars Injector instancji i uzyskać żądaną instancję z niego za pomocą

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

Można również zapisać Injector w jakiejś zmiennej globalnej, a nie korzystać z tej instancji wtryskiwacza nabyć przewidzianych instancji na przykład jak wyjaśniono w https://github.com/angular/angular/issues/4112#issuecomment-153811572

+1

Przechowywanie iniektora w globalnym var w bootstrap.then() brzmi jak to, czego potrzebuję. – dstr

+8

Pytanie mówi bez konstruktora, który czyni tę odpowiedź raczej niepomocną. –

+0

Bez konstruktora nie ma iniekcji. Czy powinniśmy usunąć to pytanie ;-) –

4

Innym podejściem polegać będzie określenie własnego dekorator (a CustomInjectable ustawić metadanych iniekcji zależnością

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

Wykorzysta metadane z konstruktora macierzystego zamiast własnych. Można go używać na klasy dziecko:

@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); 
    } 
} 

Zobacz to pytanie Więcej szczegółów:

+1

Problem polega na tym, że tsc nie pozwala mi nazywać super (argumenty), ponieważ argumenty dla konstruktora podstawowego nie są zgodne. – parliament

+1

w tym konkretnym przypadku możemy po prostu usunąć konstruktora z klasy pochodnej https://github.com/Microsoft/TypeScript/issues/12439 – slowkot

8

w zaktualizowanym kątowe, gdzie stosowane są ngModules, można utworzyć zmienną dostępny w dowolnym miejscu w kodzie:

export let AppInjector: Injector; 

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

Nice. Może być dobrą odpowiedzią na http://stackoverflow.com/questions/39409328/storing-injector-instance-for-use-in-components. – Arjan

+0

Jesteś królem! –

Powiązane problemy