如何使用Inversify + inversify-express-utils实现控制器的组件扫描/自动发现

时间:2018-08-19 02:08:43

标签: typescript inversifyjs

我正在寻找一种方法,可以在Inverseify中从@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
    ...

2 个答案:

答案 0 :(得分:0)

  1. 您必须以异步方式启动快递
  2. 您必须使用require并以异步方式导入控制器, 这应该 : 等待require(''./ controllers / StarwarsNamesController');

答案 1 :(得分:0)

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

  1. 在控制器文件夹中创建index.jsindex.ts文件
  2. 像这样export * from "./your controller file path"
  3. 添加每个控制器文件