it-swarm.com.de

Wie erweitere ich eine Komponente mit Dependency Injection?

Ich habe die folgende Klasse ModuleWithHttp:

@Injectable()
export default class {
  constructor(private fetchApi: FetchApi) {}
}

und ich möchte es wie folgt verwenden:

@Component({
  selector: 'main',
  providers: [FetchApi]
})
export default class extends ModuleWithHttp {
  onInit() {
    this.fetchApi.call();
  }
}

Durch die Erweiterung einer Superklasse, die bereits eine Abhängigkeit enthält, möchte ich einen Zugriff auf diese Klasse in ihren untergeordneten Klassen erhalten.

Ich habe viele verschiedene Wege ausprobiert, sogar mit Superklasse als Komponente:

@Component({
  providers: [FetchApi]
})
export default class {
  constructor(private fetchApi: FetchApi) {}
}

Aber dennoch, this.fetchApi ist null, auch in der Oberklasse.

31
Kamil Lelonek

Sie müssen fetchAPI in die Superklasse einfügen und an die untergeordnete Klasse weitergeben

export default class extends ModuleWithHttp {

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

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

Dies ist eine Funktion der allgemeinen Funktionsweise von DI. Die übergeordnete Klasse instanziiert das untergeordnete Element über die Vererbung, Sie müssen jedoch die erforderlichen Parameter für das untergeordnete Element angeben.

38
TGH

Wenn Sie vermeiden möchten, dass dieser "Boiler Plate" -Code Dienste in untergeordneten Klassen einfügt, nur um sie in den Konstruktor der übergeordneten Klassen einzufügen, und diese Dienste dann effektiv in untergeordneten Klassen durch Vererbung verwenden, können Sie dies tun:

edit: from Angular 5.0.0 ReflectiveInjector wurde zugunsten von StaticInjector verworfen. Der folgende Code wurde aktualisiert, um diese Änderung widerzuspiegeln.

Eine Servicekarte mit deps haben,

export const services: {[key: string]: {provide: any, deps: any[], useClass?: any}} = {
  'FetchApi': {
    provide: FetchApi,
    deps: []
  }
}

Einen Injektorhalter haben,

import {Injector} from "@angular/core";

export class ServiceLocator {
  static injector: Injector;
}

richten Sie es in AppModule ein,

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

benutze den Injektor in der Elternklasse,

export class ParentClass {

  protected fetchApi: FetchApi;

  constructor() {
    this.fetchApi = ServiceLocator.injector.get(FetchApi);
    ....
  }
}

und erweitern Sie die übergeordnete Klasse, damit Sie den FetchApi -Dienst nicht injizieren müssen.

export class ChildClass extends ParentClass {
  constructor() {
    super();
    ...
  }

  onInit() {
    this.fetchApi.call();
  }
}
67
Petr Marek

Vielleicht verspätete Antwort, aber ich hatte beschlossen, nur den Injektor auf der BaseComponent und in allen Unterklassen zu injizieren. Auf diese Weise muss kein Service-Locator gepflegt werden.

Meine Basisklasse:

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

Meine Kinderklassen:

constructor( private injector: Injector) {

   super(injector);

}
22
Rogerio