Получение экземпляра службы без вставки конструктора
У меня есть служба @Injectable
, определенная в бутстрапе. Я хочу получить экземпляр службы без использования инъекции конструктора. Я попытался использовать ReflectiveInjector.resolveAndCreate
, но, похоже, создал новый экземпляр.
Причина, по которой я пытаюсь сделать, - это базовый компонент, полученный многими компонентами. Теперь мне нужно получить доступ к службе, но я не хочу добавлять ее в ctor, потому что я не хочу вводить эту службу во все производные компоненты.
TL;DR: Мне нужен ServiceLocator.GetInstance<T>()
UPDATE: Обновлен код для RC5 +: Хранение экземпляра инжектора для использования в компонентах
Ответы
Ответ 1
Да, ReflectiveInjector.resolveAndCreate()
создает новый и несвязанный экземпляр инжектора.
Вы можете ввести экземпляр Angulars Injector
и получить из него желаемый экземпляр с помощью
constructor(private injector:Injector) {
injector.get(MyService);
}
Вы также можете сохранить Injector
в некоторой глобальной переменной и использовать этот экземпляр инжектора для получения предоставленных экземпляров, например, как описано в https://github.com/angular/angular/issues/4112#issuecomment-153811572
Ответ 2
В обновленном Angular, где используются ngModules, вы можете создать переменную, доступную в любом месте кода:
export let AppInjector: Injector;
export class AppModule {
constructor(private injector: Injector) {
AppInjector = this.injector;
}
}
Ответ 3
Другой подход состоял бы в определении пользовательского декоратора (a CustomInjectable
для установки метаданных для инъекции зависимостей:
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);
}
}
Он будет использовать метаданные из родительского конструктора вместо своих собственных. Вы можете использовать его в дочернем классе:
@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);
}
}
См. этот вопрос для получения дополнительной информации: