Angular依赖注入官方文档的学习笔记

providers: [
        {
          provide: CheckoutDeliveryService,
          useClass: MockCheckoutDeliveryService,
        },

A dependency provider configures an injector with a DI token, which that injector uses to provide the concrete, runtime version of a dependency value. The injector relies on the provider configuration to create instances of the dependencies that it injects into components, directives, pipes, and other services.

provider使用一个DI token配置injector,后者使用该token创建一个具体的能用于运行时的实例,该实例可以注入到Component,指令,管道和其他服务里。

下列两种写法等价:

  • providers: [Logger]
  • [{ provide: Logger, useClass: Logger }]

provide字段:holds the token that serves as the key for both locating a dependency value and configuring the injector.

存储了一个token,作为定位一个依赖值和配置injector的key.

第二个值是provider definition object,provider的定义对象,告诉injector如何创建被依赖的值。除了useClass之外,还有useExisting, useValue, useFactory等等。

The second property is a provider definition object, which tells the injector how to create the dependency value. The provider-definition key can be useClass, as in the example. It can also be useExisting, useValue, or useFactory. Each of these keys provides a different type of dependency, as discussed below.

不同的class可以provide同一个服务。

下列代码的含义是,如果有代码需要一个Logger,那么返回一个BetterLogger实例。

[{ provide: Logger, useClass: BetterLogger }]

看下面这段代码:

@Injectable()
export class EvenBetterLogger extends Logger {
  constructor(private userService: UserService) { super(); }

  log(message: string) {
    const name = this.userService.user.name;
    super.log(`Message to ${name}: ${message}`);
  }
}

正确的injector配置方式:

[ UserService,
  { provide: Logger, useClass: EvenBetterLogger }]

Value providers

有时我们也可以让injector返回一个事先准备好的对象,即value provider的配置。

比如下面这个对象:

// An object in the shape of the logger service
function silentLoggerFn() {}

export const SilentLogger = {
  logs: ['Silent logger says "Shhhhh!". Provided via "useValue"'],
  log: silentLoggerFn
};

使用useValue返回这个对象:

[{ provide: Logger, useValue: SilentLogger }]

如何只注入一个简单的字符串呢?

export const HERO_DI_CONFIG: AppConfig = {
  apiEndpoint: 'api.heroes.com',
  title: 'Dependency Injection'
};

The HERO_DI_CONFIG constant conforms to the AppConfig interface. Unfortunately, you cannot use a TypeScript interface as a token. In TypeScript, an interface is a design-time artifact, and doesn’t have a runtime representation (token) that the DI framework can use.

TypeScript里的接口是一个design time的概念,而DI框架需要一个运行时载体即DI token,因此接口并不能直接参与到Angular的DI中去。

解决方案1

在NgModule里提供和注入configuration对象:

providers: [
  UserService,
  { provide: APP_CONFIG, useValue: HERO_DI_CONFIG }
],

解决方案2

使用InjectionToken object.

import { InjectionToken } from '@angular/core';

export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');

现在就可以注册依赖了:

providers: [{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }]

在任何构造函数里可以使用这个依赖:

constructor(@Inject(APP_CONFIG) config: AppConfig) {
  this.title = config.title;
}

猜你喜欢

转载自blog.csdn.net/i042416/article/details/109084811