简体   繁体   English

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

[英]How to achieve component scanning/auto discovery of Controllers using Inversify + inversify-express-utils

I am looking for a way to load my controller classes in Inversify that are annotated with @controller() from inversify-express-utils without needing to manage a hand crafted/manually constructed module of imports/exports.我正在寻找一种在 Inversify 中加载我的控制器类的方法,这些类从inversify-express-utils使用@controller()进行注释,而无需管理手工制作/手动构建的导入/导出模块。

All of the examples I am seeing seem to indicate that in your entry file you need to import each of your controllers explicitely so that inversify-express-utils picks up on the @controller annotations, however this feels like it would be rather tedious for applications of a medium to large size.我看到的所有示例似乎都表明,在您的入口文件中,您需要明确地导入每个控制器,以便inversify-express-utils接收@controller注释,但是这对于应用程序来说似乎相当乏味中到大尺寸。

In plain JavaScript I would do something like recursively require each file in a directory at runtime, however I understand that due to the way TypeScript works, this isn't exactly possible?在纯 JavaScript 中,我会在运行时递归地要求目录中的每个文件,但是我理解由于 TypeScript 的工作方式,这不可能完全实现?

Using the inversify-binding-decorators package, I am able to simply annotate a service with @provide() and that seems to be enough to have the class added to the IOC container, however that does not seem to be enough for inversify-express-utils to discover the @controller() annotations on the class.使用inversify-binding-decorators包,我可以简单地使用@provide()注释服务,这似乎足以将该类添加到 IOC 容器中,但是对于inversify-express-utils似乎还不够inversify-express-utils来发现类上的@controller()注释。

Is there a way to achieve auto discovery of these @controller() annotated classes without manually importing them into a entry file?有没有办法在不手动将它们导入入口文件的情况下实现这些@controller()注释类的自动发现?

/services/StarwarsNamesService.ts /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 /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 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 :)');
});

Thrown Error:抛出错误:

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
    ...
  1. you must initiate express in async way您必须以异步方式启动 express
  2. you must import controller using require and also in async way, it should : await require(''./controllers/StarwarsNamesController');您必须使用 require 和异步方式导入控制器,它应该: await require(''./controllers/StarwarsNamesController');

You can do the following to expose your controllers您可以执行以下操作来公开您的控制器

  1. Create index.js or index.ts file in your controller folder在控制器文件夹中创建index.jsindex.ts文件
  2. add each controller file like this export * from "./your controller file path"添加这样的每个控制器文件export * from "./your controller file path"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM