Подтвердить что ты не робот

Получение экземпляра службы без вставки конструктора

У меня есть служба @Injectable, определенная в бутстрапе. Я хочу получить экземпляр службы без использования инъекции конструктора. Я попытался использовать ReflectiveInjector.resolveAndCreate, но, похоже, создал новый экземпляр.

Причина, по которой я пытаюсь сделать, - это базовый компонент, полученный многими компонентами. Теперь мне нужно получить доступ к службе, но я не хочу добавлять ее в ctor, потому что я не хочу вводить эту службу во все производные компоненты.

TL;DR: Мне нужен ServiceLocator.GetInstance<T>()

UPDATE: Обновлен код для RC5 +: Хранение экземпляра инжектора для использования в компонентах

4b9b3361

Ответ 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);
  }
}

См. этот вопрос для получения дополнительной информации: