【问题标题】:Angular 7+ - Injection and SubclassAngular 7+ - 注入和子类
【发布时间】:2020-03-16 11:52:00
【问题描述】:

通常,当您有一些可注入的服务要使用时,您会编写如下内容:

export class MyClass {
 constructor(
                private _myservice: MyService)
  { }
  [...]
}

不幸的是,当你扩展 MyClass 时,子构造函数在调用 super 时需要注入相同的服务。

export class MyClassSon extends MyClass {
   constructor()
   {
       super(); <<<---- ERROR!!!!
   }

我很困惑。我使用 SuperClass 来允许子类访问可注入服务,而无需自己注入它们。

我找到的最佳解决方案是 Injector:

export class MyClass {
     constructor(
                    injector: Injector)
      { 
          this._myservice = injector.get(MyService);
          this._fooservice = injector.get(FooService);
          //others services...
    }
}

export class MyClassSon extends MyClass {
       constructor(injector: Injector)
       {
           super(injector);
           //I can use any other services
       }

这将超级调用的复杂性降到最低,但我仍然很生气,我需要做这个技巧。

是否有另一种方法可以在不使用 costructor 的情况下在类中注入一些东西,这样我就可以让它尽可能干净,并且只用于特定组件的初始化?

【问题讨论】:

  • 您是否需要MyClassSon 中不需要的MyClass 中的服务?
  • 通过构造函数注入是当服务没有超类时你总是做的事情。当服务具有超类时,为什么会有所不同?只需做简单、简单、自然、琐碎、可测试的事情:通过构造函数注入,并使用所需的参数调用 super()。或者使用委托而不是继承。
  • @Nicolas MyClass 是一个入口点,因此扩展它的每个组件都可以访问所有服务。如果一个子类需要一个特定的服务,它只会为自己注入它。我想我不明白你的问题。
  • 这能回答你的问题吗? Inheritance and dependency injection
  • 永远不要对组件使用继承

标签: angular typescript


【解决方案1】:

如果你绝对想让你的构造函数保持干净,你可以使用 CoreModule 的静态字段中的注入器(例如)。不建议这样做,但它有效。

首先你应该从你的 CoreModule/AppModule (root) 中检索你的 Injector

export class CoreModule {
  public static injector: Injector;

  public constructor(injector: Injector) {
    CoreModule.injector = injector;
  }
}

在 MyClass 中

export class MyClass {
  public constructor() {
    this.myService = CoreModule.injector.get(MyService)
  }
}

在 MyClassSon 中

export class MyClassSon extends MyClass {
  public constructor() {
    super(); // required for invoke parent build
  }
}

您可以在 MyClass 中使用另一种不需要从子级调用 super() 构造函数的替代方法。

export class MyClass implements OnInit {
  public ngOnInit() {
    this.myService = CoreModule.injector.get(MyService)
  }
}

但对于最后一个要小心,不要在不调用父级的情况下在子级中覆盖 ngOnInit 方法。

此解决方案不符合最佳实践,但运行良好。


编辑

使用抽象类。

export abstract class MyClass {
  protected abstract get myService();
}
export class MyClassSon extends MyClass {
  protected get myService() {
    return this._myService;
  }

  public construction(private _myService: MyService) {

  }
}

【讨论】:

  • 嗨!谢谢你的回答。这比我在构造函数中使用注入器的解决方案更干净。还有一个问题:您说的不是最佳实践。在这种情况下,我们必须使用哪种设计模式?如何集中所有注入以在子类中使用?
  • 我不确定此解决方案是否存在模式。但它可能是模式的组合。我正在考虑继承、单例和依赖注入。您可以通过将 MyClass 抽象化并让 MyClassSon 提供服务来使事情变得更智能(我修改了我的帖子)
  • 我正在使用静态注入器解决方案,但我找不到在 app.module.ts 中加载它的方法。如果我把它当作一个组件,它需要“@component”和一个模板。如果我把它当作模块,它需要 NgModule。如果不将其包含在 app.module 中,则在 MyClass CoreModule.injector 中未定义
  • 你应该使用 NgModule。首先,您应该创建 CoreModule(一个 NgModule)并将其导入您的 AppModule(根 NgModule)。然后使用 CoreModule 构造函数,您可以检索 Injector 并将其链接到您的静态字段(在 CoreModule 内)。
猜你喜欢
  • 2019-07-02
  • 2020-03-14
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 2019-09-19
  • 2018-04-21
  • 2020-12-18
相关资源
最近更新 更多