【问题标题】:Angular2 Dependency Injection by Factory Method using Interface使用接口的工厂方法的Angular2依赖注入
【发布时间】:2020-03-28 13:02:56
【问题描述】:

我正在尝试使用 Angular2 依赖注入,但收到以下错误消息:

错误 NG2003:“PaymentService”类的参数“服务”没有合适的注入令牌

app.module.ts - 带有工厂方法的提供者

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    PaypalPayment,
    CardPayment,
    {
      provide: PaymentService,
      useFactory: () => {
        return new PaymentService(new PaypalPayment());
      }
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

payment.service.ts - 可注入的支付服务

@Injectable()
export class PaymentService {

  constructor(private service: Payment) {
  }

  pay(amount: number) {
    console.log('Payment Service -> pay(...) is running');
    this.service.pay(amount);
  }
}

payment.interface.ts、card-payment.ts、paypal-payment.ts文件

export interface Payment {
  pay(amount: number);
}

@Injectable()
export class CardPayment implements Payment {
  pay(amount: number) {
    console.log('Paid by card. Amount=', amount);
  }
}

@Injectable()
export class PaypalPayment implements Payment {
  pay(amount: number) {
    console.log('Paid via Paypal. Amount=', amount);
  }
}

注意:如果我将 PaymentService 文件中的“Payment”接口替换为其实现之一(PaymalPayment 或 CardPayment),一切正常。但是那里有一个接口是很常见的情况。

The full source code is here

  1. git 克隆https://github.com/karenmargaryan/di-via-interfaces-issue
  2. cd di-via-interfaces-issue
  3. npm 安装
  4. ng 服务

【问题讨论】:

    标签: angular angular-dependency-injection


    【解决方案1】:

    payment.service.ts 中:

    更新构造函数

    //import { Inject } from '@angular/core';
    
    constructor(@Inject(Payment) private service: Payment)
    

    【讨论】:

    • 您的版本正在运行。非常感谢您的回复。但是你明白我的版本有什么问题吗?我什至找到了我在 Ari Lerner 的书中写的例子,但他的版本也不起作用。
    • 当然,不客气。为了在构造函数中注入服务,服务类型应该被修饰为@Injectable(),这通常在你使用“ng g s”CLI命令时完成。在您的情况下,您尝试注入 Payment 类型的服务,而 Payment 未装饰为 @Injectable() 因此您应该通过 @Inject() 进行手动注入。如果您发现答案有益,请不要忘记将答案标记为已接受 :)
    • 我同意你关于装饰器的观点,但这里有一个例外。如果我不创建“Payment”的实例(它是一个接口),并且我在那里注入了一些东西,那么我为什么要用“Injectable()”来装饰。如果你只是用基类(没有装饰器)替换接口,它将完美地工作。据我了解,这与您的回答背道而驰。我对吗?所以这里的主要秘密是为什么这适用于“类支付”而不适用于“接口支付”......无论如何,谢谢你的努力和解释。
    • @Inject 装饰器仅用于注入原语。基本类型是数字、字符串、布尔值、大整数、符号、空值、未定义或对象。在你的情况下,接口被认为是原始的,所以它需要这个装饰器。
    猜你喜欢
    • 1970-01-01
    • 2012-08-09
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2020-03-18
    • 1970-01-01
    相关资源
    最近更新 更多