问题 Angular 2有条件地在组件中注入服务


例如:

我有2项服务

1) one.service.ts

2) two.service.ts

我有一个组件 - dashboard.component.ts

import { Component, ViewEncapsulation, Inject } from '@angular/core';
import { OneService } from '../services/one.service';
import { TwoService } from '../services/two.service';

@Component({
  selector: 'dashboard',
  encapsulation: ViewEncapsulation.Emulated,
  styleUrls: ['./dashboard.less'],
  templateUrl: './dashboard.html'
})
export class DashboardComponent {
    constructor() {
       // Here how do I get service instance based on some this condition.
         if(true) {
             /* Service **one.service.ts** to be injected */
         } else {
             /* Service **two.service.ts** to be injected */    
         }

    }
}

4446
2018-04-17 11:08


起源

使用 useFactory 要么 injector.get - yurzui
或者可以创建DashboardComponent的特定实例。这个组件在使用两个服务方面的多态性似乎很奇怪。当然,我可能错了,因为我们错过了域上下文 - Sebas
检查这个类似的问题我要求在angular2中正确处理IoC: stackoverflow.com/a/42422835/1291428 - Sebas


答案:


你可以使用 Injector

import { Injector } from '@angular/core'  
...
constructor(private injector: Injector){ 

  if(true) {
    this.oneService = <OneService>this.injector.get(OneService);
  } else {
    this.twoService = <TwoService>this.injector.get(TwoService);
  }
}

正如@MeirionHughes所提到的,这被称为服务定位器模式:

该技术是服务定位器模式的示例。

避免 这种技术,除非你真的需要它。它鼓励像你在这里看到的粗心的抓包方法。这很难解释,理解和测试。你无法通过检查构造函数来了解这个类需要什么或它将做什么。它可以从任何祖先组件获取服务,而不仅仅是它自己的组件。您不得不通过实施来发现它的作用。

框架开发人员在必须一般性地动态获取服务时可以采用这种方法。

资源: https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#explicit-injector

如上所述,您可以在另一个服务中获取这些注入器,然后将此服务注入到您的组件中。


12
2018-04-17 11:12



真棒。这样可行! - Ajey
那就是服务定位器模式;你没有注入这些服务。应将两个服务注入提供程序,然后将提供程序注入组件。 - Meirion Hughes
@MeirionHughes我添加了免责声明并感谢您在downvote之前的评论 - eko
对不起,这是不好的做法,你打破了IoC范例,这是你首先拥有(可注射)服务的唯一原因。答案在技术上是非常好的(我从中学到了),但我必须对它进行投票 - Sebas
我删除了我的投票(至少作为最后的手段有用)但我建议人们查找制作商/ Builder / Factory / Facade并避免使用injector.get() - Meirion Hughes