2

我正在寻找一种在 Inversify 中加载我的控制器类的方法,这些控制器类使用 from 进行注释,@controller()inversify-express-utils无需管理手工制作/手动构建的导入/导出模块。

我看到的所有示例似乎都表明,在您的入口文件中,您需要显式地导入每个控制器,以便inversify-express-utils获取@controller注释,但是对于中型到大型的应用程序来说,这感觉相当乏味。

在纯 JavaScript 中,我会在运行时递归地要求目录中的每个文件,但是我知道由于 TypeScript 的工作方式,这不是完全可能的吗?

使用该inversify-binding-decorators包,我可以简单地注释服务,@provide()这似乎足以将类添加到 IOC 容器中,但这似乎不足以inversify-express-utils发现@controller()类上的注释。

有没有办法实现这些@controller()带注释的类的自动发现,而无需手动将它们导入入口文件?

/services/StarwarsNamesService.ts

import { provide } from 'inversify-binding-decorators';
import * as names from 'starwars-names';
import * as matchSorter from 'match-sorter';

@provide(StarwarsNamesService)
export default class StarwarsNamesService {

    public getNames(): Array<string> {
        return names.all;
    }

    public getRandomNames(count?: number): Array<string> {
        if (!count) { count = 1; }
        return names.random(count);
    }

    public searchNames(term?: string): Array<string> {
        return matchSorter(this.getNames(), term);
    }
}

/controllers/StarWarsNamesController.ts

import { inject } from 'inversify';
import { controller, httpGet } from 'inversify-express-utils';
import StarwarsNamesService from '../../starwars-names/StarwarsNamesService';

@controller('/api/starwars-names')
export default class StarWarsNamesController {

    @inject(StarwarsNamesService)
    private starwarsNamesService: StarwarsNamesService;

    @httpGet('/')
    public getAll(): any {
        return this.starwarsNamesService.getNames();
    }
}

boostrap.ts

import 'reflect-metadata';
import * as express from "express";
import * as path from 'path';
import { InversifyExpressServer } from 'inversify-express-utils';
import { buildProviderModule } from "inversify-binding-decorators";
import { Container } from 'inversify';

// Has to be explicitly imported otherwise is undiscovered
import './controllers/StarwarsNamesController.ts';

let container = new Container();

container.load(buildProviderModule());

let server = new InversifyExpressServer(container);

let serverInstance = server.build();

serverInstance.listen(3000, () => {
    console.log('Server started on port 3000 :)');
});

抛出错误:

E:\..\..\node_modules\inversify-express-utils\lib\utils.js:10
        throw new Error(constants_1.NO_CONTROLLERS_FOUND);
              ^
Error: No controllers have been found! Please ensure that you have register at least one Controller.
    at Object.getControllersFromContainer
    ...
4

2 回答 2

0

您可以执行以下操作来公开您的控制器

  1. 在您的控制器文件夹中创建index.js或归档index.ts
  2. 像这样添加每个控制器文件export * from "./your controller file path"
于 2020-12-02T15:56:55.990 回答
0
  1. 您必须以异步方式启动 express
  2. 您必须使用 require 并且以异步方式导入控制器,它应该:await require(''./controllers/StarwarsNamesController');
于 2019-07-06T13:12:20.557 回答