Гнездо Js: динамически создавать экземпляры класса - PullRequest
1 голос
/ 10 марта 2020

Вместо Singletons я хочу динамически создавать экземпляры классов в Nest Js.

Я нашел два способа:

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

    }

Мне интересно, согласуется ли это с DI способ гнезда. js

2) Второе решение будет через factory , но здесь я не знаю, как передать параметры.

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

Не совсем уверен, как продолжить здесь / правильно внедрить фабрику, так как примеры создают объект в конструкторе без параметров?

Вопрос:

Что такое NestJs способ создания этих экземпляров классов?

Правка - для B12Toastr

Модуль - получить макет или оригинал Время компиляции

providers: [
  {
    provide: 'CHIRP_SENSOR',
    useValue: process.env.SIMULATION === 'true'
      ? ChirpSensorMock
      : ChirpSensor
  },
],

Обслуживание датчика

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

  }

1 Ответ

1 голос
/ 10 марта 2020

Вы можете передать опции на ваш завод через DI через useValue или useClass

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);
      }
    },
  },
],

В качестве альтернативы, вы также можете вообще отказаться от использования фабрики и сделать решение о том, какой класс использовать во время компиляции, с помощью:

providers: [
  {
    provide: MyOptions,
    useValue: options
  },
  {
    provide: 'CHIRP_SENSOR',
    useValue: process.env.SIMULATION === 'true'
      ? ChirpSensorMock
      : ChirpSensor
  },
],

или просто:

providers: [
  {
    provide: MyOptions,
    useValue: options
  },
  {
    process.env.SIMULATION === 'true' ? ChirpSensorMock : ChirpSensor
  },
],

Если вы не используете фабрику, как описано выше, вы должны ввести параметры в ваш ChirpSensor (или Mocked Sensor) `с использованием типичного внедрения зависимостей на основе конструктора:

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

  // ...
}

В зависимости от того, обернуты ли ваши параметры в классе или в простом объекте, вы можете использовать useValue или useClass. С useClass вы должны писать меньше кода и не должны использовать декоратор @Inject, поскольку сам класс используется в качестве токена DI. Однако, если MyOptions является классом, вам не нужно использовать @Inject в любом случае для внедрения зависимости, потому что Nest JS использует класс в качестве токена DI, независимо от того, использовали ли вы useValue или useClass чтобы обеспечить зависимость ...

...