생성자 주입 없이 서비스 인스턴스를 가져오는 중
나는 있습니다@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
아직 준비되지 않았습니다.게터를 사용하면 필요할 때까지 서비스 주입을 연기할 수 있습니다.
은주있습니이장들,라는 주장이 있습니다.AService
에 BService
,그리고.BService
에 AService
형식은 나쁘지만 모든 규칙과 상황에 대한 예외가 있기 때문에 이것은 제 생각에 이 문제를 처리하는 쉽고 효과적인 방법입니다.
// 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
'programing' 카테고리의 다른 글
jdbct 템플릿을 통해 sql insert의 ID (0) | 2023.07.07 |
---|---|
Oracle에서 MySQL로 마이그레이션 (0) | 2023.07.07 |
로컬 리포지토리의 파일과 오리진 간의 차이 (0) | 2023.07.07 |
MongoDB의 다국어 데이터 모델링 (0) | 2023.07.07 |
도커 컨테이너에서 UDP 브로드캐스트 전송 (0) | 2023.07.07 |