I have a @Injectable
service defined in bootstrap. I want to get the instance of the service without using constructor injection. I tried using Reflective
Another approach would consist of defining a custom decorator (a CustomInjectable
to set the metadata for dependency injection:
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);
}
}
It will leverage the metadata from the parent constructor instead of its own ones. You can use it on the child class:
@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);
}
}
See this question for more details:
Yes, ReflectiveInjector.resolveAndCreate()
creates a new and unconnected injector instance.
You can inject Angulars Injector
instance and get the desired instance from it using
constructor(private injector:Injector) {
injector.get(MyService);
}
You also can store the Injector
in some global variable and than use this injector instance to acquire provided instances for example like explained in https://github.com/angular/angular/issues/4112#issuecomment-153811572
In the updated Angular where ngModules are used, you can create a variable available anywhere in the code:
export let AppInjector: Injector;
export class AppModule {
constructor(private injector: Injector) {
AppInjector = this.injector;
}
}
Now, you can use the AppInjector
to find any service in anywhere of your code.
import {AppInjector} from '../app.module';
const myService = AppInjector.get(MyService);
import { Injectable} from '@angular/core';
@Injectable()
export class StoreService {
static isCreating: boolean = false;
static instance: StoreService ;
static getInstance() {
if (StoreService.instance == null) {
StoreService.isCreating = true;
StoreService.instance = new StoreService ();
StoreService.isCreating = false;
}
return StoreService.instance;
}
constructor() {
if (!StoreService.isCreating) {
throw new Error('You can\'t call new in Singleton instances! Call StoreService.getInstance() instead.');
}
}
MyAlertMethod(){
alert('hi);
}
}
//call this service directly in component.ts as below:-
StoreService.getInstance().MyAlertMethod();