modulos - servicios en angular 2
Obtención de instancia de servicio sin inyección de constructor (3)
En el Angular actualizado donde se usan ngModules, puede crear una variable disponible en cualquier parte del código:
export let AppInjector: Injector;
export class AppModule {
constructor(private injector: Injector) {
AppInjector = this.injector;
}
}
Tengo un servicio
@Injectable
definido en bootstrap.
Quiero obtener la instancia del servicio sin usar la inyección del constructor.
Intenté usar
ReflectiveInjector.resolveAndCreate
pero eso parece crear una nueva instancia.
La razón por la que intento hacer es que tengo un componente base derivado de muchos componentes. Ahora necesito acceder a un servicio pero no quiero agregarlo al ctor porque no quiero inyectar el servicio en todos los componentes derivados.
TLDR: necesito un
ServiceLocator.GetInstance<T>()
ACTUALIZACIÓN: Código actualizado para RC5 +: almacenamiento de la instancia del inyector para su uso en componentes
Otro enfoque consistiría en definir un decorador personalizado (un
CustomInjectable
para establecer los metadatos para la inyección de dependencia:
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);
}
}
Aprovechará los metadatos del constructor principal en lugar de los suyos. Puede usarlo en la clase secundaria:
@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);
}
}
Vea esta pregunta para más detalles:
Sí,
ReflectiveInjector.resolveAndCreate()
crea una instancia de inyector nueva y no conectada.
Puede inyectar la instancia de Angulars
Injector
y obtener la instancia deseada utilizando
constructor(private injector:Injector) {
injector.get(MyService);
}
También puede almacenar el
Injector
en alguna variable global y luego usar esta instancia de inyector para adquirir instancias proporcionadas, por ejemplo, como se explica en
https://github.com/angular/angular/issues/4112#issuecomment-153811572