【问题标题】:How to achieve component scanning/auto discovery of Controllers using Inversify + inversify-express-utils如何使用 Inversify + inversify-express-utils 实现 Controller 的组件扫描/自动发现
【发布时间】:2019-01-25 14:07:42
【问题描述】:

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

我看到的所有示例似乎都表明,在您的入口文件中,您需要明确导入每个控制器,以便 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
    ...

【问题讨论】:

  • 你找到解决办法了吗?我有同样的错误。
  • @YiyiChen 我还没找到解决办法。

标签: typescript inversifyjs


【解决方案1】:
  1. 您必须以异步方式启动 express
  2. 您必须使用 require 和异步方式导入控制器, 这应该 : 等待 require(''./controllers/StarwarsNamesController');

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 我希望避免手动维护索引文件,因为代码库中可能有数十个(数百个?)文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    相关资源
    最近更新 更多