以角度4扩展具有依赖注入的类

时间:2018-02-19 17:01:44

标签: javascript angular typescript dependency-injection

我正在使用角度cli和角度4。 我已经创建了一些类,我的组件继承了这些类的行为!然而,在开发期间,它们的构造成长,并且在当前阶段,我需要能够允许其他人使用它们,而不需要了解它们的构造函数!

所以在dependency injection中看到Petr消化后 我尝试了,但是由于编译器给出的错误而不得不做一些调整,我想由于角度4和角度5之间存在差异!

这是我的代码:

服务定位器:

import {ReflectiveInjector} from "@angular/core";

export class ServiceLocator {
  static injector: ReflectiveInjector;
}

导入serviceLocator的模块:

ServiceLocator.injector = ReflectiveInjector.resolveAndCreate(
      Object.keys(services).map(key => ({
        provide: services[key].provide,
        useClass: services[key].provide,
        deps: services[key].deps
      }))
    );

serviceList:

import {SysFwDatesService} from '../sysDates/sysFwDates.service';
import {MatSnackBar} from '@angular/material';
import {SysFwFormSpecBuilder} from '../uiValidation/SysFwFormSpecBuilder';
import {SysFwHttpApi} from '../http/SysFwHttpApi';


export const services: {[key: string]: {provide: any, deps: any[], useClass?: any}} = {
 'SysFwDatesService': {
    provide: SysFwDatesService,
    deps: []
  },
  'MatSnackBar': {
    provide: MatSnackBar,
    deps: []
  },
  'SysFwFormSpecBuilder': {
    provide: SysFwFormSpecBuilder,
    deps: []
  },
  'SysFwHttpApi': {
    provide: SysFwHttpApi,
    deps: []
  }
}

它似乎正在运作,但它似乎已经失去了其他提供商,并期望所有提供商都以这种方式通过!

这是我得到的错误:

  

没有HttpClient的提供商! (SysFwDatesService - > SysFwHttpApi - >   HttpClient的)

我是否需要将所有内容放在servicesList中? 我做错了什么?

在我使用注射器之前一切正常!

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

HttpClientHttpClientModule中定义,并且具有依赖关系层次结构,这些依赖关系不是很容易手动列出为单个providers数组。 ReflectiveInjectorInjector不支持Angular模块,解析模块以手动获取层次结构providers是不切实际的 - 这是Angular已在内部执行的操作。

初始化服务定位器的模块也应该导入依赖模块,并且生成的注入器应该从模块注入器继承:

@NgModule({ imports: [HttpClientModule], ... })
export class AppModule {
  constructor(injector: Injector) {
    ServiceLocator.injector = ReflectiveInjector.resolveAndCreate(
      Object.keys(services).map(key => ({
        provide: services[key].provide,
        useClass: services[key].provide,
        deps: services[key].deps
      })),
      injector
    );
  }
}

顺便说一下,services对象键不用于任何东西,而且是多余的。 services可能应该是一个数组。

我强烈建议不要在现实世界的应用程序中使用这个本土服务定位器。这是一个概念的证明,它做了它所做的事情,但也是一个对框架来说不是惯用的黑客,可能会产生很多负面后果,目前可能并不明显,例如:延迟加载的模块。

建议尽可能使用框架提供的方法,这样应用程序最有可能在将来无故障。

是:

@Injectable() // needed for JIT compilation
abstract class Injective {
  constructor(protected injector: Injector) {}
}

@Injectable() // potentially needed for AOT compilation
class FooService extends Injective {
  baz = this.injector.get(Baz);
}

@Component(...)
class BarComponent extends Injective {
  foo = this.injector.get(FooService);

  // just passes injector to parent constructor if there's a need for own constructor
  constructor(injector: Injector, public baz: Baz) {
    super(injector);
    // ...
  }
}

请注意,为了安全起见,父类和子类都需要@Injectable()(Angular和Angular CLI版本之间可能会有所不同)。

答案 1 :(得分:0)

您是否尝试过HttpClient明确指定SysFwHttpApi作为依赖项?像

'SysFwHttpApi': { provide: SysFwHttpApi, deps: [HttpClient] }