基于@Input()的Angular 2动态依赖注入

Joh*_*ohn 18 dependency-injection typescript angular

假设我有一个Angular 2组件指令,我希望组件使用的注入依赖项由@Input()确定.

我想写类似的东西<trendy-directive use="'serviceA'">并让TrendyDirective的实例使用serviceA,或者让它使用serviceB,如果这是我指定的.(这是我实际尝试做的过于简单的版本)

(如果你认为这是一个可怕的想法,我会对这些反馈持开放态度,但请解释原因.)

这是如何实现我的想法的一个例子.在这个例子中,假设ServiceA和ServiceB是注入式的,它们都通过'superCoolFunction'来实现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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为这在技术上可行,但必须有更好的方法来进行动态依赖注入.

Est*_*ask 10

它是

// 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}'`);
    }
}
Run Code Online (Sandbox Code Playgroud)


A. *_*Tim 5

通常,Angular2文档中介绍了相同的方法:InjectorComponent

@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) { }
}
Run Code Online (Sandbox Code Playgroud)

您必须注入Injector构造函数并在注释providers属性中列出所有服务@Component。然后,您可以injector.get(type)在哪里type解决您的问题@Input。根据文档,Service直到您要求时(.get())才真正注入。