Angular dependency injection official document study notes

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.

The provider uses a DI token to configure the injector. The latter uses the token to create a specific instance that can be used at runtime. The instance can be injected into Component, instruction, pipeline, and other services.

The following two wordings are equivalent:

  • 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.

A token is stored as a key for locating a dependent value and configuring the injector.

The second value is the provider definition object. The definition object of the provider tells the injector how to create the dependent value. In addition to useClass, there are useExisting, useValue, useFactory, etc.

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.

Different classes can provide the same service.

The meaning of the following code is that if there is a code that requires a Logger, then a BetterLogger instance is returned.

[{ provide: Logger, useClass: BetterLogger }]

Look at the following code:

@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}`);
  }
}

The correct injector configuration method:

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

Value providers

Sometimes we can also let the injector return a pre-prepared object, the configuration of the value provider.

For example, the following object:

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

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

Use useValue to return this object:

[{ provide: Logger, useValue: SilentLogger }]

How to inject only a simple string?

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.

The interface in TypeScript is a concept of design time, and the DI framework requires a runtime carrier, namely DI token, so the interface cannot directly participate in Angular DI.

Solution 1

Provide and inject configuration objects in NgModule:

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

Solution 2

Use InjectionToken object.

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

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

Now you can register the dependencies:

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

This dependency can be used in any constructor:

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

Guess you like

Origin blog.csdn.net/i042416/article/details/109084811