NestJs:动态创建类的实例

And*_*iga 7 factory dependency-injection nestjs

我想在 NestJs 中动态创建类实例,而不是单例。

我找到了两种方法:

1)直接创建类(ChripSensor则不是@Injectable)

import { ChirpSensor } from './chirp-sensor/chirp-sensor';

@Injectable()
export class SensorsService {
  registeredSensors: any;
  constructor(
    @InjectModel('Sensor') private readonly sensorModel: Model<ISensor>,
    private i2cService: I2cService) {
       const sensors = this.i2cService.getSensors();
       sensors.forEach((sensor) => {this.registeredSensors[sensor._id] = new ChirpSensor({name: sensor.name})});

    }
Run Code Online (Sandbox Code Playgroud)

我想知道这是否与nest.js的DI方式一致

2)第二种解决方案是通过工厂,但在这里我不知道如何传递选项。

export const chirpFactory = {
  provide: 'CHIRP_SENSOR',
  useFactory: (options) => {
    console.log('USING FACTORY CHIRP, options', options)
    if (process.env.SIMULATION === 'true') {
      return new ChirpSensorMock(options);
    }
    else {
      return new ChirpSensor(options);
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

不太确定如何继续这里/正确注入工厂,因为示例在构造函数中创建对象而没有选项?

问题:

NestJs创建这些类实例的方法是什么?

编辑 - B12Toastr

模块 - 在编译时获取模拟或原始版本

providers: [
  {
    provide: 'CHIRP_SENSOR',
    useValue: process.env.SIMULATION === 'true'
      ? ChirpSensorMock
      : ChirpSensor
  },
],
Run Code Online (Sandbox Code Playgroud)

传感器服务

@Injectable()
export class SensorsService {
  registeredSensors: any;
  constructor(
    @Inject('CHIRP_SENSOR') private ChirpSensorClass: any, // any works but ChirpSensorMock | ChirpSensor not
    private i2cService: I2cService
   ) {
    const sensors = this.i2cService.getSensors();
    sensors.forEach((sensor) => {this.registeredSensors[sensor._id] = new ChirpSensorClass({name: sensor.name})});

  }
Run Code Online (Sandbox Code Playgroud)

B12*_*ter 7

您可以通过useValueuseClass通过 DI 将选项传递给您的工厂

providers: [
  {
    provide: MyOptions,
    useValue: options
  },
  {
    provide: 'CHIRP_SENSOR',
    useFactory: (options: MyOptions) => {
      console.log('USING FACTORY CHIRP, options', options);
      if (process.env.SIMULATION === 'true') {
        return new ChirpSensorMock(options);
      } else {
        return new ChirpSensor(options);
      }
    },
  },
],
Run Code Online (Sandbox Code Playgroud)

或者,您也可以完全避免使用工厂,并通过以下方式决定在编译时使用哪个类:

providers: [
  {
    provide: MyOptions,
    useValue: options
  },
  {
    provide: 'CHIRP_SENSOR',
    useValue: process.env.SIMULATION === 'true'
      ? ChirpSensorMock
      : ChirpSensor
  },
],
Run Code Online (Sandbox Code Playgroud)

或者简单地:

providers: [
  {
    provide: MyOptions,
    useValue: options
  },
  {
    process.env.SIMULATION === 'true' ? ChirpSensorMock : ChirpSensor
  },
],
Run Code Online (Sandbox Code Playgroud)

如果您没有如上所述使用工厂,则可以ChirpSensor使用典型的基于构造函数的依赖项注入将选项注入到您的(或模拟传感器)中:

@Injectable()
export class ChripSensor {
  constructor(@inject(MyOptions) private options: MyOptions) {
  }

  // ...
}
Run Code Online (Sandbox Code Playgroud)

根据您的选项是包装在类中还是简单对象中,您可以使用useValueuseClass。您必须useClass编写更少的代码,并且不必使用@Inject装饰器,因为类本身用作 DI 令牌。但是,似乎 ifMyOptions是一个类,您在任何情况下都不需要使用@Inject来注入依赖项,因为 NestJS 使用该类作为 DI 令牌,无论您是否使用useValueuseClass提供依赖项...