Skip to content

【TypeScript】简易的 IOC 容器 #62

@zh-rocco

Description

@zh-rocco

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);

参考

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions