将 inversifyJS 配置文件拆分为多个文件
Splitting inversifyJS config file into multiple files
最近接触到一个使用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
如果它在一个复杂的项目中会有多冗长和混乱。
希望有人能对此提供帮助:)
首先,文档中描述了您的问题,has a solution。
你的解决方案大体上是正确的,但存在循环依赖
./dependencies/types.ts -> ./dependencies/moduleA/index.ts -> ./dependencies/types.ts
在 types
中创建了 class 的新实例,但包含 class 定义的模块导入 types
。您没有列出此导入,但在 bind
.
中使用 TYPES.ModuleARepo
要避免它,您可以将 types
字段设为静态或将其从 class 移出到单独的可导出对象中。作为它的一个积极的副作用,将不需要在 ./dependencies/types.ts
.
中实例化 class
为了以防万一,请记住,如果您实例化一个 class,它有一个 Symbol 作为一个字段,这个符号对于自 Symbol('ModuleARepo') !== Symbol('ModuleARepo')
.
以来的每个实例都是唯一的
最近接触到一个使用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
如果它在一个复杂的项目中会有多冗长和混乱。
希望有人能对此提供帮助:)
首先,文档中描述了您的问题,has a solution。
你的解决方案大体上是正确的,但存在循环依赖
./dependencies/types.ts -> ./dependencies/moduleA/index.ts -> ./dependencies/types.ts
在 types
中创建了 class 的新实例,但包含 class 定义的模块导入 types
。您没有列出此导入,但在 bind
.
TYPES.ModuleARepo
要避免它,您可以将 types
字段设为静态或将其从 class 移出到单独的可导出对象中。作为它的一个积极的副作用,将不需要在 ./dependencies/types.ts
.
为了以防万一,请记住,如果您实例化一个 class,它有一个 Symbol 作为一个字段,这个符号对于自 Symbol('ModuleARepo') !== Symbol('ModuleARepo')
.