You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS依赖注入报错:无法解析Population的Number类型依赖

NestJS遗传算法课程排程系统依赖注入错误解决

问题描述

使用NestJS开发基于遗传算法的课程排程系统,包含geneticalgorithm.ts、data.ts、population.ts、scheduleservice.ts、schedulemodule.ts等文件。在GeneticAlgorithm类的方法中,通过构造函数调用Population类时需要传入population.getSchedules().length作为数值参数,但启动应用时出现依赖注入错误。

错误日志

[Nest] 63732  - 11/11/2024, 6:51:23 PM     LOG [NestFactory] Starting Nest application...
[Nest] 63732  - 11/11/2024, 6:51:23 PM     LOG [InstanceLoader] AppModule dependencies initialized +54ms
[Nest] 63732  - 11/11/2024, 6:51:23 PM     LOG [Instance Loader] Type Orm Module dependencies initialized +0ms
[Nest] 63732  - 11/11/2024, 6:51:23 PM     LOG [Instance Loader] Number dependencies initialized +1ms

[Nest] 63732  - 11/11/2024, 6:51:23 PM   ERROR [Exception Handler] Nest can't resolve dependencies of the Population (?, Data). Please make sure that the argument Number at index [0] is available in the ScheduleModule context.

Potential solutions:
- Is ScheduleModule a valid NestJS module?
- If Number is a provider, is it part of the current ScheduleModule?
- If Number is exported from a separate @Module, is that module imported within ScheduleModule?
  @Module({
    imports: [ /* the Module containing Number */ ]
  })

相关代码文件

geneticalgorithm.ts

import { Injectable } from '@nestjs/common';
import { Data } from './data';
import { Population } from './population';
import { Schedule } from './schedule';
import { Driver } from './driver';

@Injectable()
export class GeneticAlgorithm {
  private data: Data;

  constructor(data: Data) {
    this.data = data;
  }

  public evolve(population: Population): Population {
    return this.mutatePopulation(this.crossoverPopulation(population));
  }

  private crossoverPopulation(population: Population): Population {
    const crossoverPopulation = new Population(population.getSchedules().length, this.data);
    for (let i = 0; i < Driver.NUMB_OF_ELITE_SCHEDULES; i++) {
      crossoverPopulation.getSchedules()[i] = population.getSchedules()[i];
    }
    for (let i = Driver.NUMB_OF_ELITE_SCHEDULES; i < population.getSchedules().length; i++) {
      if (Driver.CROSSOVER_RATE > Math.random()) {
        const schedule1 = this.selectTournamentPopulation(population).sortByFitness().getSchedules()[0];
        const schedule2 = this.selectTournamentPopulation(population).sortByFitness().getSchedules()[0];
        crossoverPopulation.getSchedules()[i] = this.crossoverSchedule(schedule1, schedule2);
      } else {
        crossoverPopulation.getSchedules()[i] = population.getSchedules()[i];
      }
    }
    return crossoverPopulation;
  }

  private crossoverSchedule(schedule1: Schedule, schedule2: Schedule): Schedule {
    const crossoverSchedule = new Schedule(this.data).initialize();
    for (let i = 0; i < crossoverSchedule.getClasses().length; i++) {
      if (Math.random() > 0.5) {
        crossoverSchedule.getClasses()[i] = schedule1.getClasses()[i];
      } else {
        crossoverSchedule.getClasses()[i] = schedule2.getClasses()[i];
      }
    }
    return crossoverSchedule;
  }

  private mutatePopulation(population: Population): Population {
    const mutatePopulation = new Population(population.getSchedules().length, this.data);
    const schedules = mutatePopulation.getSchedules();
    for (let i = 0; i < Driver.NUMB_OF_ELITE_SCHEDULES; i++) {
      schedules[i] = population.getSchedules()[i];
    }
    for (let i = Driver.NUMB_OF_ELITE_SCHEDULES; i < population.getSchedules().length; i++) {
      schedules[i] = this.mutateSchedule(population.getSchedules()[i]);
    }
    return mutatePopulation;
  }

  private mutateSchedule(schedule: Schedule): Schedule {
    const mutateSchedule = new Schedule(this.data).initialize();
    for (let i = 0; i < schedule.getClasses().length; i++) {
      if (Driver.MUTATION_RATE > Math.random()) {
        schedule.getClasses()[i] = mutateSchedule.getClasses()[i];
      }
    }
    return schedule;
  }

  private selectTournamentPopulation(population: Population): Population {
    const tournamentPopulation = new Population(Driver.TOURNAMENT_SELECTION_SIZE, this.data);
    for (let i = 0; i < Driver.TOURNAMENT_SELECTION_SIZE; i++) {
      tournamentPopulation.getSchedules()[i] = population.getSchedules()[Math.floor(Math.random() * population.getSchedules().length)];
    }
    return tournamentPopulation;
  }
}

population.ts

import { Injectable } from '@nestjs/common';
import { Data } from './data';
import { Schedule } from './schedule';

@Injectable()
export class Population {
  private schedules: Schedule[];

  constructor(size: number, data: Data) {
    this.schedules = new Array<Schedule>(size);
    for (let i = 0; i < size; i++) {
      this.schedules[i] = new Schedule(data).initialize();
    }
  }

  public getSchedules(): Schedule[] {
    return this.schedules;
  }

  public sortByFitness(): Population {
    this.schedules.sort((schedule1, schedule2) => {
      let returnValue = 0;
      if (schedule1.getFitness() > schedule2.getFitness()) returnValue = -1;
      else if (schedule1.getFitness() < schedule2.getFitness()) returnValue = 1;
      return returnValue;
    });
    return this;
  }
}

schedulemodule.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Schedule } from './schedule.entity';
import { ScheduleService } from './schedule.service';
import { ScheduleController } from './schedule.controller';
import { ScheduleRepository } from './schedule.repository';
import { Data } from './data';
import { GeneticAlgorithm } from './genetic-algorithm';
import { Population } from './population';
import { Class } from './class.entity';
import { CourseModule } from '../course/course.module';
import { DepartmentModule } from '../department/department.module';
import { InstructorModule } from '../instructor/instructor.module';
import { MeetingTimeModule } from '../meeting-time/meeting-time.module';
import { RoomModule } from '../room/room.module';

@Module({
  imports: [
    TypeOrmModule.forFeature([Schedule, Class]),
    CourseModule,
    DepartmentModule,
    InstructorModule,
    MeetingTimeModule,
    RoomModule,
  ],
  providers: [ScheduleService, ScheduleRepository, Data, GeneticAlgorithm, Population],
  controllers: [ScheduleController],
})
export class ScheduleModule {}

问题原因

Population类被标记为@Injectable(),NestJS会尝试通过依赖注入系统创建它的实例,但它的构造函数需要一个动态的number类型参数size,Nest无法自动解析原始类型的依赖。而且在GeneticAlgorithm中我们是手动实例化Population,根本不需要将其注册为可注入服务。

解决方案

1. 移除Population类的@Injectable()装饰器

修改population.ts,去掉@Injectable(),因为它是工具类,不需要Nest管理生命周期:

import { Data } from './data';
import { Schedule } from './schedule';

export class Population {
  private schedules: Schedule[];

  constructor(size: number, data: Data) {
    this.schedules = new Array<Schedule>(size);
    for (let i = 0; i < size; i++) {
      this.schedules[i] = new Schedule(data).initialize();
    }
  }

  public getSchedules(): Schedule[] {
    return this.schedules;
  }

  public sortByFitness(): Population {
    this.schedules.sort((schedule1, schedule2) => {
      let returnValue = 0;
      if (schedule1.getFitness() > schedule2.getFitness()) returnValue = -1;
      else if (schedule1.getFitness() < schedule2.getFitness()) returnValue = 1;
      return returnValue;
    });
    return this;
  }
}

2. 从ScheduleModule的providers中移除Population

修改schedulemodule.ts,将Population从providers数组中删除:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Schedule } from './schedule.entity';
import { ScheduleService } from './schedule.service';
import { ScheduleController } from './schedule.controller';
import { ScheduleRepository } from './schedule.repository';
import { Data } from './data';
import { GeneticAlgorithm } from './genetic-algorithm';
import { Class } from './class.entity';
import { CourseModule } from '../course/course.module';
import { DepartmentModule } from '../department/department.module';
import { InstructorModule } from '../instructor/instructor.module';
import { MeetingTimeModule } from '../meeting-time/meeting-time.module';
import { RoomModule } from '../room/room.module';

@Module({
  imports: [
    TypeOrmModule.forFeature([Schedule, Class]),
    CourseModule,
    DepartmentModule,
    InstructorModule,
    MeetingTimeModule,
    RoomModule,
  ],
  providers: [ScheduleService, ScheduleRepository, Data, GeneticAlgorithm],
  controllers: [ScheduleController],
})
export class ScheduleModule {}

原理说明

NestJS的依赖注入系统适用于需要复用、生命周期由框架管控的服务类。像Population这种需要动态参数才能创建实例的类,应该通过手动new的方式创建,而非交给依赖注入管理。移除@Injectable()和providers中的注册后,Nest不再尝试解析它的依赖,错误即可解决。

内容的提问来源于stack exchange,提问作者engineerdavut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:27:06