# 理解IOC

# Reading

# 什么是IOC

IOC(inversion of control)即控制反转,依赖注入是IOC的一种形式。

依赖注入表现为内部依赖由外部注入,例如:类Controller依赖类Service,但并不直接在Controller构造函数中主动实例化Service,而是在构造函数接受一个Service类型的参数,其实例化的工作交给外部。这种模式带来的好处就是松耦合。

# NestJS中的IOC

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

// app.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

上述示例中AppController依赖于AppService,但是其构造函数中并没有直接实例化AppService,而是接受该类型的参数,并赋值给this.appService。实例化AppController的时候,Nest将根据AppController构造函数接受的参数类型,为其实例化相应的Service。

# 实现简单版本的依赖注入

import 'reflect-metadata'

type Constructor<T = any> = new (...args: any[]) => T

const Decorator = (): ClassDecorator => target => {}

class MyService {
  sayHello() {
    console.log('hello')
  }
}

@Decorator()
class MyController {
  constructor(private service: MyService) {}

  sayHello() {
    this.service.sayHello()
  }
}

const Factory = <T>(target: Constructor<T>): T => {
  const providers = Reflect.getMetadata('design:paramtypes', target)
  const args = providers.map((provider: any) => new provider())
  return new target(...args)
}

Factory(MyController).sayHello() // hello

reflect-metada仅作用于使用了装饰器的类 (opens new window)