如何在Angular 2中扩展具有依赖注入的组件?

时间:2015-11-28 11:12:07

标签: dependency-injection angular

我有以下课程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,即使是在超级班级。

4 个答案:

答案 0 :(得分:65)

如果你想避免这种“锅炉板”代码在子类中注入服务只是为了在父类的构造函数中注入,然后通过继承在子类中有效地使用这些服务,你可以这样做:

编辑:来自Angular 5.0.0 ReflectiveInjector已被弃用,转而使用StaticInjector,下面是更新代码以反映此更改

拥有deps的服务地图,

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

答案 1 :(得分:35)

您必须在超类中注入fetchAPI并将其传递给子类

export default class extends ModuleWithHttp {

  constructor(fetchApi: FetchApi) {
     super(fetchApi);
  }   

  onInit() {
    this.fetchApi.call();
  }
}

这是DI一般工作方式的一个特点。超类将通过继承实例化子进程,但您必须向子进程提供所需的参数。

答案 2 :(得分:19)

可能是迟到的响应,但我已经解决了只在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);

}

答案 3 :(得分:0)

app.run(host='0.0.0.0')

请注意,尽管MyService1和MyService2是MyBaseClass创建的新实例