[angular] 생성자 주입없이 서비스 인스턴스 가져 오기

@Injectable부트 스트랩에 정의 된 서비스 가 있습니다 . 생성자 주입을 사용하지 않고 서비스 인스턴스를 가져오고 싶습니다. 나는 사용해 ReflectiveInjector.resolveAndCreate보았지만 새 인스턴스를 만드는 것 같습니다.

내가하려는 이유는 많은 구성 요소에서 파생 된 기본 구성 요소가 있기 때문입니다. 이제 서비스에 액세스해야하지만 모든 파생 구성 요소에 서비스를 주입하고 싶지 않기 때문에 ctor에 추가하고 싶지 않습니다.

TLDR : 나는 ServiceLocator.GetInstance<T>()

업데이트 : RC5 +에 대한 업데이트 된 코드 : 구성 요소에 사용할 인젝터 인스턴스 저장



답변

예, ReflectiveInjector.resolveAndCreate()연결되지 않은 새 인젝터 인스턴스를 생성합니다.

Angulars Injector인스턴스 를 삽입 하고 다음을 사용하여 원하는 인스턴스를 가져올 수 있습니다.

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

또한 Injector일부 전역 변수에 를 저장 하고이 인젝터 인스턴스를 사용하여 예를 들어 https://github.com/angular/angular/issues/4112#issuecomment-153811572에 설명 된 것처럼 제공된 인스턴스를 획득 할 수 있습니다.


답변

ngModules가 사용되는 업데이트 된 Angular에서 코드의 모든 위치에서 사용 가능한 변수를 만들 수 있습니다.

export let AppInjector: Injector;

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

이제를 사용 AppInjector하여 코드 어디에서나 서비스를 찾을 수 있습니다.

import {AppInjector} from '../app.module';

const myService = AppInjector.get(MyService);


답변

또 다른 접근 방식은 사용자 지정 데코레이터 ( 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);
  }
}

자세한 내용은이 질문을 참조하십시오.


답변

StoreService .ts

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

component.ts

//call this service directly in component.ts as below:-

 StoreService.getInstance().MyAlertMethod();


답변