programing

생성자 주입 없이 서비스 인스턴스를 가져오는 중

powerit 2023. 7. 7. 21:12
반응형

생성자 주입 없이 서비스 인스턴스를 가져오는 중

나는 있습니다@Injectable부트스트랩에 정의된 서비스입니다.나는 컨스트럭터 인젝션을 사용하지 않고 서비스의 인스턴스를 받고 싶습니다.사용해 보았습니다.ReflectiveInjector.resolveAndCreate하지만 그것은 새로운 사례를 만들어내는 것 같습니다.

제가 시도하는 이유는 많은 구성요소에 의해 파생된 기본 구성요소가 있기 때문입니다.이제 서비스에 액세스해야 하지만 모든 파생 구성 요소에 서비스를 주입하고 싶지 않기 때문에 생성자에 서비스를 추가하고 싶지 않습니다.

TLDR: 나는 필요합니다.ServiceLocator.GetInstance<T>()

업데이트: RC5+용 코드 업데이트: 구성 요소에 사용할 인젝터 인스턴스 저장

ngModules가 사용되는 업데이트된 Angular에서 코드의 모든 위치에서 사용할 수 있는 변수를 생성할 수 있습니다.

이 코드를 app.module.ts에 추가합니다.

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

export let AppInjector: Injector;
    
export class AppModule {
  constructor(private injector: Injector) {
    AppInjector = this.injector;
  }
}

이제 사용할 수 있습니다.AppInjector모든 코드에서 서비스를 찾을 수 있습니다.

import { AppInjector } from '../app.module';

const myService = AppInjector.get(MyService);

네.ReflectiveInjector.resolveAndCreate()연결되지 않은 새 인젝터 인스턴스를 만듭니다.

Angulars를 주입할 수 있습니다.Injector인스턴스를 사용하여 원하는 인스턴스를 가져옵니다.

constructor(private injector:Injector) {
  injector.get(MyService);
}

또한 저장할 수 있습니다.Injector일부 글로벌 변수에서 인젝터 인스턴스를 사용하여 제공된 인스턴스를 획득합니다(예: https://github.com/angular/angular/issues/4112#issuecomment-153811572 참조).

또 다른 접근 방식은 사용자 지정 장식자(a)를 정의하는 것으로 구성됩니다.CustomInjectable종속성 주입에 대한 메타데이터를 설정하는 방법

export function CustomComponent(annotation: any) {
  return function (target: Function) {

    // DI configuration
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
    var parentAnnotations = Reflect.getMetadata('design:paramtypes', parentTarget);

    Reflect.defineMetadata('design:paramtypes', parentAnnotations, target);

    // Component annotations / metadata
    var annotations = Reflect.getOwnMetadata('annotations', target);
    annotations = annotations || [];
    annotations.push(annotation);
    Reflect.defineMetadata('annotations', annotations, target);
  }
}

자신의 메타데이터 대신 상위 생성자의 메타데이터를 활용합니다.하위 클래스에서 사용할 수 있습니다.

@Injectable()
export class SomeService {
  constructor(protected http:Http) {
  }
}

@Component()
export class BaseComponent {
  constructor(private service:SomeService) {
  }
}

@CustomComponent({
  (...)
})
export class TestComponent extends BaseComponent {
  constructor() {
    super(arguments);
  }

  test() {
    console.log('http = '+this.http);
  }
}

자세한 내용은 이 질문을 참조하십시오.

이 문제에 몇 번 부딪힌 후, 저는 Angular와 함께 Getter를 사용하여 이 문제를 극복할 수 있는 좋은 방법을 고안했습니다.Injector서비스 대신 생성자에 서비스를 직접 주입합니다.이를 통해 서비스 시간을 참조하기 전에 구성할 수 있습니다.이 예에서는 서비스만 사용하지만 서비스를 사용하는 구성 요소에도 동일한 것을 적용할 수 있습니다. 대신 구성 요소에 게터를 넣으십시오.BService예문에서

제가 한 일은 게터를 사용하여 클래스 속성에 서비스를 주입하는 것이었습니다.Injector클래스(클래스 속성이 아직 설정되지 않은 경우). 따라서 서비스는 한 번만 주입됩니다(게터가 처음 호출될 때).이를 통해 서비스를 생성자에 주입한 것과 기본적으로 동일한 방식으로 사용할 수 있지만 순환 참조 오류가 발생하지 않습니다.그냥 게터를 사용하세요.this.aService이 기능이 작동하지 않을 때는 사용하려는 경우뿐입니다.AService의틀안서의 에서.Bservice그러면 당신은 같은 순환 참조 문제를 갖게 될 것입니다.Aservice아직 준비되지 않았습니다.게터를 사용하면 필요할 때까지 서비스 주입을 연기할 수 있습니다.

은주있습니이장들,라는 주장이 있습니다.AServiceBService,그리고.BServiceAService형식은 나쁘지만 모든 규칙과 상황에 대한 예외가 있기 때문에 이것은 제 생각에 이 문제를 처리하는 쉽고 효과적인 방법입니다.

// a.service.ts
import { Injectable } from '@angular/core';

import { BService } from './b.service';

@Injectable({
  providedIn: 'root'
})
export class AService {

  constructor(
    private bService: BService,
  ) { }

  public foo() {
    console.log('foo function in AService!');
    this.bService.bar();
  }
}
// b.service.ts
import { Injectable, Injector } from '@angular/core';

import { AService } from './a.service';


@Injectable({
  providedIn: 'root'
})
export class BService {
  // Use the getter 'aService' to use 'AService', not this variable.
  private _aService: AService;

  constructor(
    private _injector: Injector,
  ) { }

  // Use this getter to use 'AService' NOT the _aService variable.
  get aService(): AService {
    if (!this._aService) {
      this._aService = this._injector.get(AService);
    }
    return this._aService;
  }

  public bar() {
    console.log('bar function in BService!');
    this.aService.foo();
  }
}

서비스 .ts 저장

  import { Injectable} from '@angular/core';
    
    @Injectable()
    export class StoreService {
      static isCreating: boolean = false;
      static instance: StoreService ;
    
      static getInstance() {
        if (StoreService.instance == null) {
          StoreService.isCreating = true;
          StoreService.instance = new StoreService ();
          StoreService.isCreating = false;
        }
        return StoreService.instance;
      }
      constructor() {
        if (!StoreService.isCreating) {
          throw new Error('You can\'t call new in Singleton instances! Call StoreService.getInstance() instead.');
        }
     }
    
  MyAlertMethod(){
    alert('hi);
    }
  }

.ts

//call this service directly in .ts as below:-

 StoreService.getInstance().MyAlertMethod();

언급URL : https://stackoverflow.com/questions/37482460/getting-instance-of-service-without-constructor-injection

반응형