web-dev-qa-db-ja.com

コンストラクター注入なしでサービスのインスタンスを取得する

ブートストラップで@Injectableサービスが定義されています。コンストラクター注入を使用せずにサービスのインスタンスを取得したい。 ReflectiveInjector.resolveAndCreateを使用してみましたが、新しいインスタンスが作成されるようです。

私がやろうとしている理由は、多くのコンポーネントから派生した基本コンポーネントがあるからです。ここで、サービスにアクセスする必要がありますが、派生コンポーネントのすべてにサービスを注入したくないので、それをctorに追加したくありません。

TLDR:ServiceLocator.GetInstance<T>()が必要です

UPDATE:RC5 +のコードを更新: コンポーネントで使用するインジェクターインスタンスを保存

55
dstr

はい、ReflectiveInjector.resolveAndCreate()は新しい未接続のインジェクターインスタンスを作成します。

Angulars Injectorインスタンスを注入し、それから目的のインスタンスを取得できます

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

Injectorをグローバル変数に保存し、このインジェクターインスタンスを使用して、たとえば https://github.com/angular/angular/issues/4112#issuecomment -153811572

56

NgModuleが使用される更新されたAngularでは、コード内の任意の場所で利用可能な変数を作成できます。

export let AppInjector: Injector;

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

別のアプローチでは、カスタムデコレータ(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);
  }
}

詳細については、この質問を参照してください。

5