programing

상속 및 의존성 주입

megabox 2023. 4. 24. 23:01
반응형

상속 및 의존성 주입

나는 모든 서비스를 받을 수 있는 angular2 컴포넌트 세트를 가지고 있다.처음에는 슈퍼클래스를 만들어 거기에 서비스를 투입하는 것이 가장 좋다고 생각했습니다.내 컴포넌트 중 어떤 것이든 슈퍼클래스를 확장할 수 있지만 이 접근방식은 작동하지 않습니다.

간단한 예:

export class AbstractComponent {
  constructor(private myservice: MyService) {
    // Inject the service I need for all components
  }
}

export MyComponent extends AbstractComponent {
  constructor(private anotherService: AnotherService) {
    super(); // This gives an error as super constructor needs an argument
  }
}

이 문제를 해결할 수 있는 방법은MyService 에서 이 합니다.super()전화는 했지만 그건 확실히 말도 안 되는 소리예요

슈퍼클래스의 서비스를 상속할 수 있도록 컴포넌트를 올바르게 정리하려면 어떻게 해야 합니까?

각각의 컴포넌트에 MyService를 삽입하여 그 인수를 super() 호출에 사용하는 것으로 해결할 수 있었습니다만, 이것은 확실히 터무니없는 것입니다.

말도 안 돼요.이것이 컨스트럭터 및 컨스트럭터 주입의 작동 방식입니다.

주입 또, 슈퍼 는, 해, 「」와 .super(dep1, dep2)discl.discl.discl을 클릭합니다.

주입기를 돌리고 의존성을 획득하는 것은 반드시 심각한 단점이 있습니다.

종속성을 숨겨 코드를 읽기 어렵게 만듭니다.
Angular2 DI를 사용합니다.
퍼포먼스를 향상시키고 코드 크기를 줄이기 위해 선언형 및 필수 DI를 대체하는 정적 코드를 생성하는 오프라인 컴파일을 중단합니다.

솔루션이 업데이트되어 글로벌 인젝터를 사용하여 myService의 여러 인스턴스가 생성되지 않습니다.

import {Injector} from '@angular/core';
import {MyServiceA} from './myServiceA';
import {MyServiceB} from './myServiceB';
import {MyServiceC} from './myServiceC';

export class AbstractComponent {
  protected myServiceA:MyServiceA;
  protected myServiceB:MyServiceB;
  protected myServiceC:MyServiceC;

  constructor(injector: Injector) {
    this.settingsServiceA = injector.get(MyServiceA);
    this.settingsServiceB = injector.get(MyServiceB);
    this.settingsServiceB = injector.get(MyServiceC);
  }
}

export MyComponent extends AbstractComponent {
  constructor(
    private anotherService: AnotherService,
    injector: Injector
  ) {
    super(injector);

    this.myServiceA.JustCallSomeMethod();
    this.myServiceB.JustCallAnotherMethod();
    this.myServiceC.JustOneMoreMethod();
  }
}

이렇게 하면 파생된 모든 클래스에 MyService를 삽입할 필요 없이 Abstract Component를 확장하는 모든 클래스에서 MyService를 사용할 수 있습니다.

이 솔루션에는 몇 가지 단점이 있습니다(아래의 @Günter Zöchbauer의 Comment 참조).

  • 글로벌 인젝터를 주입하는 것은 여러 곳에서 주입해야 하는 여러 다른 서비스가 있는 경우에만 개선됩니다.공유 서비스를 1개만 사용하는 경우 파생 클래스 내에 해당 서비스를 삽입하는 것이 더 쉽고 편리할 수 있습니다.
  • 제 솔루션과 그가 제안한 대안 모두 어떤 클래스에 어떤 서비스가 달려 있는지 알아보기 어렵게 만든다는 단점이 있습니다.

Angular2에서의 의존관계 주입에 대한 자세한 설명은 다음 블로그 포스트를 참조하십시오.http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html

모든 서비스를 수동으로 주입하는 대신 서비스를 제공하는 클래스를 만들었습니다. 예를 들어 서비스가 주입됩니다.그런 다음 이 클래스는 파생 클래스에 삽입되어 기본 클래스로 전달됩니다.

파생 클래스:

@Component({
    ...
    providers: [ProviderService]
})
export class DerivedComponent extends BaseComponent {
    constructor(protected providerService: ProviderService) {
        super(providerService);
    }
}

기본 클래스:

export class BaseComponent {
    constructor(protected providerService: ProviderService) {
        // do something with providerService
    }
}

서비스 제공 클래스:

@Injectable()
export class ProviderService {
    constructor(private _apiService: ApiService, private _authService: AuthService) {
    }
}

다른 모든 서비스를 종속성으로 하는 서비스를 주입하는 대신 다음과 같이 하십시오.

class ProviderService {
    constructor(private service1: Service1, private service2: Service2) {}
}

class BaseComponent {
    constructor(protected providerService: ProviderService) {}

    ngOnInit() {
        // Access to all application services with providerService
        this.providerService.service1
    }
}

class DerivedComponent extends BaseComponent {
    ngOnInit() {
        // Access to all application services with providerService
        this.providerService.service1
    }
}

이 추가 단계를 건너뛰고 다음과 같이 Base Component에 모든 서비스를 추가합니다.

class BaseComponent {
    constructor(protected service1: Service1, protected service2: Service2) {}
}

class DerivedComponent extends BaseComponent {
    ngOnInit() {
        this.service1;
        this.service2;
    }
}

이 기술은 다음 2가지를 상정하고 있습니다.

  1. 고객님의 관심사는 전적으로 컴포넌트 상속과 관련되어 있습니다.대부분의 경우, 이 질문을 받게 된 이유는 파생된 각 클래스에서 반복해야 하는 건조하지 않은(WET?) 코드가 너무 많기 때문입니다.모든 컴포넌트 및 서비스에 대해 단일 엔트리 포인트의 이점을 얻으려면 추가 단계를 수행해야 합니다.

  2. 가 ""를 합니다.BaseComponent

한 경우에도 는 파생 클래스의 컨스트럭터를 호출해야 입니다.super()모든 의존관계들을 넘겨주죠이 기능을 사용할 필요가 있는 유스케이스는 잘 모르겠습니다.constructorngOnInit가 존재할 있습니다

Angular 하는 Angular v14는 매우 합니다.inject() https://angular.io/api/core/inject,. 이제 컨스트럭터 외부에 있는 "필드 이니셜라이저"에서 종속성을 설정할 수 있습니다.

관계,즉 토큰 의존관계는 다음과 같습니다.DOCUMENT ★★★★★★★★★★★★★★★★★」LOCALE_ID예를 들면.

import { DOCUMENT } from '@angular/common';
import { inject } from '@angular/core';

export abstract class AbstractComponent {
  abstractDependency = inject(DOCUMENT);
}
import { Component, inject, LOCALE_ID } from '@angular/core';
import { AbstractComponent } from './abstract.component';

@Component({
  selector: 'my-app',
  template: '{{ abstractDependency }} {{ myDependency }}',
})
export class MyComponent extends AbstractComponent {
  myDependency = inject(LOCALE_ID);
}

라이브 예: https://stackblitz.com/edit/angular-ivy-zvlx1d?file=src/app/my.component.ts

제가 알기로는 기본 클래스에서 상속받으려면 먼저 인스턴스화해야 합니다.이를 인스턴스화하기 위해서는 컨스트럭터에 필요한 파라미터를 전달해야 합니다.따라서 super() 호출을 통해 자녀에서 부모로 전달해야 합니다.물론 주입기는 또 다른 실행 가능한 해결책이다.

못생긴 해킹

얼마 전 제 고객 중 일부는 어제의 두 개의 빅 앵글 프로젝트에 참여하기를 원합니다(앵글 v4에서 앵글 v8로).프로젝트 v4는 각 컴포넌트에 대해 BaseView클래스를 사용하고 있습니다.이 클래스에는 다음이 포함됩니다.tr(key)method for translate (v8에서는 ng-translate를 사용합니다)번역 시스템을 전환하지 않고 수백 개의 템플릿을 편집하거나(v4), 2개의 번역 시스템을 병렬로 셋업하기 위해 추악한 해킹(자랑스럽지 않음)을 사용합니다.AppModule클래스 다음 생성자를 추가합니다.

export class AppModule { 
    constructor(private injector: Injector) {
        window['UglyHackInjector'] = this.injector;
    }
}

그리고 지금AbstractComponent사용할 수 있습니다.

export class AbstractComponent {
  private myservice: MyService = null;

  constructor() {
    this.myservice = window['UglyHackInjector'].get(MyService);
  }
}

서드파티제 플러그인에서 부모 클래스를 취득한 경우(원본을 변경할 수 없는 경우) 다음을 수행할 수 있습니다.

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

export MyComponent extends AbstractComponent {
  constructor(
    protected injector: Injector,
    private anotherService: AnotherService
  ) {
    super(injector.get(MyService));
  }
}

또는 가장 좋은 방법(생성자에 한 개의 매개 변수만 유지):

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

export MyComponent extends AbstractComponent {
  private anotherService: AnotherService;

  constructor(
    protected injector: Injector
  ) {
    super(injector.get(MyService));
    this.anotherService = injector.get(AnotherService);
  }
}

언급URL : https://stackoverflow.com/questions/39038791/inheritance-and-dependency-injection

반응형