首页 > 解决方案 > 为服务扩展类时如何处理 NestJS 依赖注入?

问题描述

我正在尝试根据我的ConfigService.

findOne()我遇到的问题是,在执行(result is null) 或countDocuments()(result is )等查询方法时,注入的 mongoose 模型不返回任何值0

我的服务类定义如下:

    export class BaseService {
      constructor(@InjectModel('Cat') public readonly catModel: Model<Cat>) {}

      createService(option: string) {
        if (option === 'OTHER') {
          return new OtherService(this.catModel);
        } else if (option === 'ANOTHER') {
          return new AnotherService(this.catModel);
        } else {
          return new BaseService(this.catModel);
        }
      }

      async findOne(id: string): Promise<Cat> {
        return await this.catModel.findOne({_id: id});
      }

      async count(): Promise<number> {
        return await this.catModel.countDocuments();
      }

      testClass() {
        console.log('BASE SERVICE CLASS USED');
      }
    }

    @Injectable()
    export class OtherService extends BaseService {
      constructor(@InjectModel('Cat') public readonly catModel: Model<Cat>) {
        super(catModel);
      }

       testClass() {
        console.log('OTHER SERVICE CLASS USED');
      }
    }

    @Injectable()
    export class AnotherService extends BaseService {
      constructor(@InjectModel('Cat') public readonly catModel: Model<Cat>) {
        super(catModel);
      }
      testClass() {
        console.log('ANOTHER SERVICE CLASS USED');
      }
    }

这使我可以从我的提供者那里获得正确的服务(testClass()打印预期的字符串)。我的提供者如下所示:

    export const catProviders = [
      {
        provide: 'CatModelToken',
        useFactory: (connection: Connection) => connection.model('CAT', CatSchema),
        inject: ['DbConnectionToken'],
      },
      {
        provide: 'BaseService',
        useFactory: (ConfigService: ConfigService, connection: Connection) => {
          const options = ConfigService.get('SERVICE_TYPE');
          let model = connection.model('CAT', CatSchema);
          return new BaseService(model).createService(options);
      },
      inject: [ConfigService, 'CatModelToken', 'DbConnectionToken'],
      }
    ];

所以我的问题分为两部分:

我也不能使用useClass文档中的示例,因为我需要能够注入ConfigService.

标签: mongoosedependency-injectionsubclassextendsnestjs

解决方案


您可以通过使用工厂方法来解决这个问题,试试这个:

确定服务“形状”的接口:

export interface IDatabaseService {
    findOne(id: string): Promise<Cat>;
    count(): Promise<number>;
    testClass(): void;
}

BaseService 必须实现该接口:

export class BaseService implements IDatabaseService {

    constructor(@InjectModel('Cat') public readonly catModel: Model<Cat>) {}

    async findOne(id: string): Promise<Cat> {
        return await this.catModel.findOne({_id: id});
    }

    async count(): Promise<number> {
        return await this.catModel.countDocuments();
    }

    testClass() {
        console.log('BASE SERVICE CLASS USED');
    }
}

动态服务未注入,因此它们不使用@Injectable()装饰器:

export class OtherService extends BaseService {

    constructor(@InjectModel('Cat') public readonly catModel: Model<Cat>) {
        super(catModel);
    }

    testClass() {
        console.log('OTHER SERVICE CLASS USED');
    }
}

export class AnotherService extends BaseService {

    constructor(@InjectModel('Cat') public readonly catModel: Model<Cat>) {
        super(catModel);
    }

    testClass() {
        console.log('ANOTHER SERVICE CLASS USED');
    }
}

工厂类是被注入的东西:

@Injectable()
export class DatabaseServiceFactory {

    constructor(@InjectModel('Cat') private readonly catModel: Model<Cat>) {}

    createService(name: string) : IDatabaseService {
        switch(name) {
            case 'other': return new OtherService(this.catModel);
            case 'another': return new AnotherService(this.catModel);
            default: throw new Error(`No service has been implemented for the name "${name}"`);
        }
    }
}
export const catProviders = [
    {
        provide: 'CatModelToken',
        useFactory: (connection: Connection) => connection.model('CAT', CatSchema),
        inject: ['DbConnectionToken'],
    },
    {
        provide: 'BaseService',
        useFactory: (ConfigService: ConfigService, connection: Connection, dbFactory: DatabaseServiceFactory) => {

            const options = ConfigService.get('SERVICE_TYPE');
            let model = connection.model('CAT', CatSchema);
            
            //return new BaseService(model).createService(options);
            return dbFactory.createService(options);
        },
        inject: [
            ConfigService,
            'CatModelToken',
            'DbConnectionToken',
            DatabaseServiceFactory
        ],
    }
];

推荐阅读