@Input()에 기반한 Angular 2 동적 종속성 주입
Angular 2 성분 지침이 있다고 가정합니다. 여기서 성분이 사용하는 주입된 종속성이 @Input()에 의해 결정되기를 원합니다.
저는 다음과 같은 것을 쓰고 싶습니다.<trendy-directive use="'serviceA'">
그리고 트렌디 디렉티브의 인스턴스가 A 서비스를 사용하도록 하거나, 만약 그것이 내가 지정한 것이라면 B 서비스를 사용하도록 합니다.(이것은 제가 실제로 하려고 하는 것을 지나치게 단순화한 버전입니다.)
(처음에 이것이 좋지 않은 생각이라고 생각하신다면, 저는 그 피드백에 동의합니다. 하지만 그 이유를 설명해 주십시오.)
여기 제가 생각하는 것을 성취하는 방법의 한 가지 예가 있습니다.이 예에서 서비스 A와 서비스 B가 모두 '슈퍼 쿨 기능'을 통해 iService를 구현하는 주입식이라고 상상해 보십시오.
@Component({
selector: 'trendy-directive',
...
})
export class TrendyDirective implements OnInit {
constructor(
private serviceA: ServiceA,
private serviceB: ServiceB){}
private service: iService;
@Input() use: string;
ngOnInit() {
switch (this.use){
case: 'serviceA': this.service = this.serviceA; break;
case: 'serviceB': this.service = this.serviceB; break;
default: throw "There's no such thing as a " + this.use + '!';
}
this.service.superCoolFunction();
}
}
저는 이것이 기술적으로 효과가 있을 것이라고 생각하지만, 동적 의존성 주입을 하는 더 나은 방법이 있을 것입니다.
그렇다.
// can be a service also for overriding and testing
export const trendyServiceMap = {
serviceA: ServiceA,
serviceB: ServiceB
}
constructor(private injector: Injector) {}
...
ngOnInit() {
if (trendyServiceMap.hasOwnProperty(this.use)) {
this.service = this.injector.get<any>(trendyServiceMap[this.use]);
} else {
throw new Error(`There's no such thing as '${this.use}'`);
}
}
일반적으로 동일한 접근 방식은 Angular2 설명서에 설명되어 있습니다.인젝터 구성 요소
@Component({
providers: [Car, Engine, Tires, heroServiceProvider, Logger]
})
export class InjectorComponent {
car: Car = this.injector.get(Car);
heroService: HeroService = this.injector.get(HeroService);
hero: Hero = this.heroService.getHeroes()[0];
constructor(private injector: Injector) { }
}
주입해야 합니다.Injector
생성자에서 모든 서비스 나열providers
의 재산.@Component
주석그러면 할 수 있습니다.injector.get(type)
,어디에type
에서 해결됩니다.@Input
문서에 따르면,Service
요청하기 전까지는 실제로 주입되지 않습니다..get()
).
이름을 배열 개체로 선언할 필요 없이 Estus Flask의 답변을 한 단계 더 진행하여 서비스를 가져오는 논리를 만들고 싶습니다.
기본적으로, 우리는 그냥 지나치면 됩니다.path
그리고.name
서비스와 나머지는 거의 같습니다.
public _dynamicService: any;
dynamicDI(service_path, service_name){
import(service_path).then(s => {
this._dynamicService = this.injector.get<any>(s['service_name']);
})
}
이제 내부의 기능에 액세스할 수 있습니다.dynamicService
다음과 같이:
(필요한 서비스에 http 관찰 가능한 fn이 있다고 가정합니다.)
this._dynamicService['your_function_name']().subscribe(res=> { console.log(res) } );
여기 약간 복잡하지만 매력적으로 일하는 방법이 있습니다!
공유 모듈 및 다중 사용자 지정 구현에서 기본 검색 서비스를 설정합니다.그리고 가능한 모든 구현을 명시적으로 참조할 필요가 없습니다.
인터페이스 및 기본 구현
export interface ISearch {
searchByTerm(textInput: string);
}
export class DefaultSearch implements ISearch {
searchByTerm(textInput: string) { console.log("default search by term"); }
}
Injection을 사용하여 서비스 구현 목록 생성상품권
// Keep list of token, provider will give a implementation for each of them
export const SearchServiceTokens: Map<string, InjectionToken<ISearch>> = new Map();
// Add File service implementation token
SearchServiceTokens.set('default', new InjectionToken<ISearch>('default'));
기본 서비스 구현을 위한 공급자
providers: [
...
// Default implementation service
{
provide: SearchServiceTokens.get('default'),
useClass: DefaultSearch
}
]
사용자 정의 구현(다른 모듈에 있을 수 있음)
export class Component1Search implements ISearch {
searchByTerm(textInput: string) { console.log("component1 search by term"); }
}
사용자 정의 구현을 위한 토큰 추가
SearchServiceTokens.set('component1', new InjectionToken<ISearch>('component1'));
공급자 추가
providers: [
...
// Other implementation service
{
provide: SearchServiceTokens.get('component1'),
useClass: Component1Search
}
]
마지막으로, 당신의 구성 요소에서
@Input() useService;
searchService: ISearch;
constructor(private injector: Injector) {
// Use default if none provided
let serviceToUse = 'default';
if (null !== this.useService) { serviceToUse = this.useService; }
this.searchService = this.injector.get(SearchServiceTokens.get(serviceToUse));
}
Inject in @angular/core module이라는 서비스가 있습니다.@Inject를 사용하면 대체 주입 방법을 얻을 수 있습니다.그러나 이것은 시공자에서만 가능합니다.
따라서 구성요소의 입력을 @구성요소 장식자의 입력 배열에 넣은 다음(클래스 내에서 @입력 장식자를 사용하지 않음) 해당 입력 변수를 생성자에 주입해야 합니다.
너무 늦었을 수도 있지만 어떤 상황에서 동적 주입을 위한 흥미롭고 깔끔한 해결책이 있을 수 있습니다.주요 아이디어는 서비스 래퍼를 사용하고 필요한 서비스의 적절한 인스턴스를 가져오기 위한 메소드 또는 게터를 추가하는 것입니다.
@Injectable({
providedIn: 'root',
})
export class CredentialsServiceImp {
constructor(
private visitorService: VisitorCredentialsServiceImp,
private employeeService: EmployeeCredentialsServiceImp
) {
}
instance(userType:UserType): UserCredentialsService {
return userType == UserType.employee ? this.employeeService : this.visitorService;
}
}
모두 및 사용자 CredentialsService를 합니다.instance
getter는 조건에 따라 적절한 인스턴스로 얻어집니다.사용자 구성 요소에서 사용
export class Component implements OnInit {
@Input() userType : UserType;
constructor(
private credentials: CredentialsServiceImp
) {
}
ngOnInit(): {
const service = this.credentials.instance(this.userType);
}
}
언급URL : https://stackoverflow.com/questions/41366108/angular-2-dynamic-dependency-injection-based-on-input
'sourcecode' 카테고리의 다른 글
MongoDB_id(ObjectId)가 오름차순으로 생성됩니까? (0) | 2023.07.13 |
---|---|
웹 배포 작업에 실패했습니다.('Microsoft'의 이니셜라이저입니다.웹, 배포.'배포 관리자'에서 예외를 발생시켰습니다.) (0) | 2023.07.13 |
vuex를 사용하여 어레이 상태를 제어하는 방법은 무엇입니까? (0) | 2023.07.13 |
새 Firebase 콘솔에서 데이터베이스 및 스토리지 사용량을 확인하는 방법 (0) | 2023.07.13 |
IntelliJ IDEA 엔드포인트 탭을 표시하지 않음: "응용 프로그램 JMX 서비스 URL을 검색하지 못했습니다." (0) | 2023.07.13 |