网站搜索

node.js - 将 inversifyJS 配置文件拆分成多个文件


我最近遇到了一个使用 TypeScript 的后端项目,并且想使用 Inversify.js 来实现 IoC 原则。按照官方文档,我有一个名为 inversify.config.ts 的大文件,里面包含了我所有的接口和实现这些接口的类:

import "reflect-metadata"
import { Container } from "inversify"
import TYPES from './types';

import { ModuleRepo } from '../repo/interfaces'
import { ModuleARepoImpl } from '../repo/moduleA'
import { ModuleBRepoImpl } from '../repo/moduleB'

import { ModuleService } from '../services/interfaces'
import { ModuleAServiceImpl } from '../services/moduleA'
import { ModuleBServiceImpl } from '../services/moduleB'

const container = Container();

container.bind<ModuleRepo>(TYPES.ModuleARepo).to(ModuleARepoImpl);
container.bind<ModuleRepo>(TYPES.ModuleBRepo).to(ModuleBRepoImpl);

container.bind<ModuleService>(TYPES.ModuleAService).to(ModuleAServiceImpl);
container.bind<ModuleService>(TYPES.ModuleBService).to(ModuleBServiceImpl);

export default container;

上述环境中的一个大问题是,当项目变得复杂时,会添加更多模块,从而导致配置文件非常长(想象一下你有几十个模块)。我的计划是将其分成更小的配置文件,同时inversify.config.ts仍然是主文件。

考虑以下设置:

./dependencies/interface/index.ts

import { Container } from 'inversify';
export type InversifyContainer = Container

export interface BasicInterface {
        register(container: InversifyContainer): void
        readonly types: Object
    }

./dependencies/moduleA/index.ts

import {InversifyContainer, BasicDependencies} from '../interface';
import { ModuleRepo } from '../../repo/interfaces'
import { ModuleARepoImpl } from '../../repo/moduleA'
import { ModuleService } from '../../services/interfaces'
import { ModuleAServiceImpl } from '../../services/moduleA'

export class ModuleADependencies {
    register(container: InversifyContainer) {
           container.bind<ModuleRepo>(TYPES.ModuleARepo).to(ModuleARepoImpl);
           container.bind<ModuleService>(TYPES.ModuleAService).to(ModuleAServiceImpl);
    }

    readonly types = {
          ModuleARepo: Symbol('ModuleARepo'),
          ModuleAService: Symbol('ModuleAService'),
    }
}

./dependencies/inversify.config.ts

import "reflect-metadata"
import { Container } from "inversify"

import { ModuleADependencies } from './moduleA';
import { ModuleBDependencies } from './moduleB'; // consider moduleB also has the same file

const container = Container();
const registrationList = [ModuleADependencies, ModuleBDependencies];
for (const reg of registrationList) {
    new reg().register(container);
}

export default container;

./dependencies/types.ts

import { ModuleADependencies } from './moduleA';
import { ModuleBDependencies } from './moduleB';

const TYPES = {
    ...(new ModuleADependencies().types),
    ...(new ModuleBDependencies().types),
}

export default TYPES

然而,这种方式我总是会出现一个错误,显示类似 Cannot read property of ModuleARepo of undefined 的类型错误。我在网上浏览过,但似乎没有人关心如果在一个复杂项目中,inversify.config.ts 会变得多么冗长和混乱。

希望有人可以帮忙 :)

答案#1

首先,你的问题在文档中有描述,并且有解决方案。

你的解决方案总体上是正确的,但存在循环依赖

./dependencies/types.ts -> ./dependencies/moduleA/index.ts -> ./dependencies/types.ts

在 types 中创建了类的新实例,但包含类定义的模块导入了 types。你没有列出这个导入,但在 bind 中使用了 TYPES.ModuleARepo。

为了避免它,你可以将 types 字段设为静态,或者将其移出类,放入一个单独的可导出对象中。这样,一个积极的副作用是,在 ./dependencies/types.ts 中就不需要实例化类了。

以防万一,请记住,如果你实例化一个类,而该类有一个 Symbol 作为字段,那么这个 Symbol 对每个实例都是唯一的,因为 Symbol('ModuleARepo') !== Symbol('ModuleARepo')。

操场