tsconfig 设置
tsconfig.json
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"emitDecoratorMetadata": true,
"experimentalDecorators": true
},
"exclude": ["node_modules"]
}
IOC 容器
ioc.ts
import 'reflect-metadata';
interface InjectableClass {
new (...args: any[]): any;
}
const classPool: Array<InjectableClass> = [];
export function injectable(target: InjectableClass) {
const params: Array<InjectableClass> = Reflect.getMetadata(
'design:paramtypes',
target,
);
console.log('injectable:', `<${target.name}>`, params);
if (classPool.includes(target)) {
return;
}
if (params && params.length) {
for (const param of params) {
if (param === target) {
throw new Error('不可以依赖自身');
}
if (!classPool.includes(param)) {
throw new Error(`依赖 <${param.name}> 不可被注入`);
}
}
}
classPool.push(target);
}
export function inject<T>(target: { new (...args: any[]): T }): T {
const params: Array<InjectableClass> = Reflect.getMetadata(
'design:paramtypes',
target,
);
console.log('inject:', `<${target.name}>`, params);
const paramInstances = params.map(param => {
if (!classPool.includes(param)) {
throw new Error(`依赖 <${param.name}> 不可被注入`);
}
if (param.length) {
return inject(param);
}
return new param();
});
return new target(...paramInstances);
}
使用
index.ts
import { injectable, inject } from './ioc';
@injectable
class B {
public title = 'B';
}
@injectable
class C {
constructor(private b: B) {}
public title = 'C';
}
@injectable
class D {
public title = 'D';
}
class E {
public title = 'E';
}
@injectable
class A {
constructor(private c: C, private d: D) {
console.log('A:', c.title, d.title);
}
}
const a = inject(A);
console.log(a);
参考
tsconfig 设置
tsconfig.json{ "compilerOptions": { "target": "es2018", "module": "commonjs", "emitDecoratorMetadata": true, "experimentalDecorators": true }, "exclude": ["node_modules"] }IOC 容器
ioc.ts使用
index.ts参考