次のクラスModuleWithHttp
があります。
@Injectable()
export default class {
constructor(private fetchApi: FetchApi) {}
}
そして、私はそれを次のように使いたい:
@Component({
selector: 'main',
providers: [FetchApi]
})
export default class extends ModuleWithHttp {
onInit() {
this.fetchApi.call();
}
}
そのため、既に依存関係を注入しているスーパークラスを拡張することで、その子にアクセスできるようにします。
コンポーネントとしてスーパークラスを持っていても、私は多くの異なる方法を試しました:
@Component({
providers: [FetchApi]
})
export default class {
constructor(private fetchApi: FetchApi) {}
}
それでも、 this.fetchApi
は、スーパークラスであってもnull
です。
スーパークラスにfetchAPIを注入し、それを子クラスに渡す必要があります
export default class extends ModuleWithHttp {
constructor(fetchApi: FetchApi) {
super(fetchApi);
}
onInit() {
this.fetchApi.call();
}
}
これは、一般的なDIの機能の特徴です。スーパークラスは、継承を介して子をインスタンス化しますが、必要なパラメーターを子に提供する必要があります。
親クラスのコンストラクターでの注入のためだけに子クラスでサービスを注入するこの「ボイラープレート」コードを回避し、継承を通じて子クラスでそのサービスを効果的に使用する場合、これを行うことができます。
編集:from Angular 5.0.0 ReflectiveInjectorはStaticInjectorの代わりに廃止されました。この変更を反映するために以下のコードが更新されます
深さのあるサービスマップを用意し、
export const services: {[key: string]: {provide: any, deps: any[], useClass?: any}} = {
'FetchApi': {
provide: FetchApi,
deps: []
}
}
インジェクターホルダーを持っている、
import {Injector} from "@angular/core";
export class ServiceLocator {
static injector: Injector;
}
appModuleで設定し、
@NgModule(...)
export class AppModule {
constructor() {
ServiceLocator.injector = Injector.create(
Object.keys(services).map(key => ({
provide: services[key].provide,
useClass: services[key].provide,
deps: services[key].deps
}))
);
}
}
親クラスでインジェクターを使用し、
export class ParentClass {
protected fetchApi: FetchApi;
constructor() {
this.fetchApi = ServiceLocator.injector.get(FetchApi);
....
}
}
FetchApi
サービスを注入する必要がないように、親クラスを拡張します。
export class ChildClass extends ParentClass {
constructor() {
super();
...
}
onInit() {
this.fetchApi.call();
}
}
応答が遅れるかもしれませんが、BaseComponentおよびすべてのサブクラスでインジェクターのみをインジェクトすることを解決したため、サービスロケーターを維持する必要はありません。
私の基本クラス:
constructor(private injectorObj: Injector) {
this.store = <Store<AppState>>this.injectorObj.get(Store);
this.apiService = this.injectorObj.get(JsonApiService);
this.dialogService = this.injectorObj.get(DialogService);
this.viewContainerRef = this.injectorObj.get(ViewContainerRef);
this.router = this.injectorObj.get(Router);
this.translate = this.injectorObj.get(TranslateService);
this.globalConstantsService = this.injectorObj.get(GlobalConstantsService);
this.dialog = this.injectorObj.get(MatDialog);
this.activatedRoute = this.injectorObj.get(ActivatedRoute);
}
私の子供のクラス:
constructor( private injector: Injector) {
super(injector);
}