2016-12-28 55 views
10

假設我有一個Angular 2組件指令,其中我希望組件使用的注入依賴由@Input()確定。基於@Input的角度2動態依賴注入()

我想寫一些類似<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(); 
    } 
} 

我認爲這在技術上是可行的,但是有一個更好的方法來做動態依賴注入。

回答

4

它是

// 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}'`); 
    } 
} 
+0

由於4.0'get'已被棄用。 –

+0

我的意思是簽名。請參閱https://github.com/angular/angular/blob/5.2.5/packages/core/src/di/injector.ts#L62 –

+0

使用類型調用泛型方法總是更好。我不確定這個簽名是否會被刪除。它可以讓用戶知道使用泛型更好。無論如何,我更新了答案,感謝您的關注。通常我不打擾徹底輸入解決方案,並專注於提供它的要點。 – estus

2

有一個@角/芯模塊在名爲進樣的服務。使用@Inject您可以實現替代注射方式。但是這隻能在構造函數中完成。

所以你需要將組件的輸入放入你的@component裝飾器的輸入數組(不要在類裏面使用@Input裝飾器),然後在構造函數中注入輸入變量。

+1

我也會爲注射投票: 您是否會在其父組件中多次使用trendy-directive或將其切換爲動態?如果沒有,父組件可以簡單地提供正確的服務,而且不需要實現複雜的邏輯。 '''@Component({selector:'i-use-trendy-directive',providers:[{provide:MyServiceInterfase,useClass:MyServiceImpl}]}'''然後'''構造函數(private myService:MyServiceInterface){} '' –

+0

在我的情況下,我會在不止一個地方使用不同服務的指令,謝謝 – John

+0

@Vineet'DEVIN'Dev這非常有趣,裝飾器中輸入數組的文檔看起來很稀疏。在'@ Component'裝飾器中的元素在組件生命週期中的地址比'@ Input'裝飾器中指定的更早。 – John

3

一般來說,同樣的方法也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) { } 
} 

必須注入在構造Injector@Component註釋providers屬性列表中的所有服務。那麼你可以injector.get(type),其中type將從您的@Input解決。根據文件,Service實際上並沒有注入,直到你要求它(.get())。