返回 AiToEarn
container.ts
1 /*
2 * @Author: nevin
3 * @Date: 2025-01-24 17:55:15
4 * @LastEditTime: 2025-01-24 19:50:24
5 * @LastEditors: nevin
6 * @Description: 容器
7 */
8 import { INJECT_METADATA_KEY } from './metadata';
9 // import { AppDataSource } from '../../db';
10
11 // 创建一个容器类来管理依赖注入
12 export class Container {
13 private static instance: Container;
14 private readonly providers = new Map<string, any>();
15 private readonly providerClasses = new Map<string, any>();
16 private readonly controllers = new Map<string, any>();
17 // 用于检测循环依赖
18 private readonly dependencyStack: string[] = [];
19
20 private constructor() {}
21
22 static getInstance(): Container {
23 if (!Container.instance) {
24 Container.instance = new Container();
25 }
26 return Container.instance;
27 }
28
29 // 注册 provider 类
30 registerProvider(providerClass: any) {
31 const providerName = providerClass.name;
32 if (!this.providerClasses.has(providerName)) {
33 // 检查依赖关系
34 this.checkCircularDependencies(providerClass);
35 this.providerClasses.set(providerName, providerClass);
36 }
37 }
38
39 // 检查循环依赖
40 private checkCircularDependencies(
41 targetClass: any,
42 visited = new Set<string>(),
43 ) {
44 const className = targetClass.name;
45
46 if (visited.has(className)) {
47 const dependencyPath = [...visited, className].join(' -> ');
48 throw new Error(`Circular dependency detected: ${dependencyPath}`);
49 }
50
51 visited.add(className);
52
53 const injections =
54 Reflect.getMetadata(INJECT_METADATA_KEY, targetClass) || [];
55 for (const { serviceType } of injections) {
56 const dependencyClass = serviceType;
57 this.checkCircularDependencies(dependencyClass, new Set(visited));
58 }
59 }
60
61 // 获取或创建 provider 实例
62 getProvider(name: string) {
63 if (this.dependencyStack.includes(name)) {
64 throw new Error(
65 `Circular dependency detected: ${[...this.dependencyStack, name].join(
66 ' -> ',
67 )}`,
68 );
69 }
70
71 if (!this.providers.has(name)) {
72 const providerClass = this.providerClasses.get(name);
73 if (!providerClass) {
74 throw new Error(`Provider ${name} not registered`);
75 }
76
77 this.dependencyStack.push(name);
78 const instance = new providerClass();
79 this.injectDependencies(instance, providerClass);
80 this.dependencyStack.pop();
81
82 this.providers.set(name, instance);
83 }
84 return this.providers.get(name);
85 }
86
87 // 注入依赖
88 private injectDependencies(instance: any, targetClass: any) {
89 const injections =
90 Reflect.getMetadata(INJECT_METADATA_KEY, targetClass) || [];
91 injections.forEach(({ propertyKey, serviceType }: any) => {
92 instance[propertyKey] = this.getProvider(serviceType.name);
93 });
94 }
95
96 // Controller 相关方法
97 setController(name: string, controller: any) {
98 if (!this.controllers.has(name)) {
99 this.injectDependencies(controller, controller.constructor);
100 this.controllers.set(name, controller);
101 }
102 }
103
104 getController(name: string) {
105 return this.controllers.get(name);
106 }
107
108 hasController(name: string) {
109 return this.controllers.has(name);
110 }
111
112 getAllProviders() {
113 return this.providers;
114 }
115
116 getAllControllers() {
117 return this.controllers;
118 }
119
120 // 添加初始化方法
121 async initialize() {
122 // 初始化所有已注册的 providers
123 for (const [name, providerClass] of this.providerClasses.entries()) {
124 if (!this.providers.has(name)) {
125 const instance = new providerClass();
126 this.injectDependencies(instance, providerClass);
127 this.providers.set(name, instance);
128 }
129 }
130 }
131 }
132
133 export const container = Container.getInstance();
134
134 lines TYPESCRIPT