web-dev-qa-db-ja.com

Angular 5サービスの交換/オーバーライド

いくつかのコンポーネントとサービスを含むプロジェクトのコアライブラリを作成しました。 ng-packagrを使用してライブラリを構築しました。ライブラリを参照する消費プロジェクトで、ライブラリによって提供されるコンポーネントを含むWebアプリケーションを構築しました。これまでのところ特別なことは何もありません。しかし、libの外部のサービスからメソッドを呼び出すコンポーネント(libから来る)が必要な場合があります。これは可能ですか?ライブラリ内で定義されているコンポーネントにサービスを注入できますか?

乾杯

6
Baerree

私は以前に次のようなものでこれを達成しました:

ライブラリのサービスは、具体的な実装としてではなく、インターフェイスとして定義する必要があります(OO言語で頻繁に行われるように))実装アプリケーションがたまにしか受け渡したくない場合サービスの独自のバージョンの場合は、ライブラリにデフォルトサービスを作成し、次のように使用する必要があります。

import { Component, NgModule, ModuleWithProviders, Type, InjectionToken, Inject, Injectable } from '@angular/core';

export interface ILibService {
  aFunction(): string;
}

export const LIB_SERVICE = new InjectionToken<ILibService>('LIB_SERVICE');

export interface MyLibConfig {
  myService: Type<ILibService>;
}

@Injectable()
export class DefaultLibService implements ILibService {
  aFunction() {
    return 'default';
  }
}

@Component({
  // whatever
})
export class MyLibComponent {
  constructor(@Inject(LIB_SERVICE) libService: ILibService) {
    console.log(libService.aFunction());
  }
}

@NgModule({
  declarations: [MyLibComponent],
  exports: [MyLibComponent]
})
export class LibModule {
  static forRoot(config?: MyLibConfig): ModuleWithProviders {
    return {
      ngModule: LibModule,
      providers: [
        { provide: LIB_SERVICE, useClass: config && config.myService || DefaultLibService }
      ]
    };
  }
}

次に、実装するアプリケーションで、ライブラリのforRootメソッドを介してオプションの構成を渡すことができます(forRootは、アプリケーションごとに1回だけ、可能な限り最高レベルで呼び出す必要があることに注意してください)。 configパラメーターをオプションとしてマークしたので、渡す構成がない場合でもforRootを呼び出す必要があることに注意してください。

import { NgModule, Injectable } from '@angular/core';
import { LibModule, ILibService } from 'my-lib';

@Injectable()
export class OverridingService implements ILibService {
  aFunction() {
    return 'overridden!';
  }
}

@NgModule({
  imports: [LibModule.forRoot({ myService: OverridingService })]
})
export class ImplementingModule {

}

現時点で渡すコードがないため、これはメモリからのものでした。何らかの理由で機能しない場合は、お知らせください。

9
UncleDave