tsyringe 的介绍文章不多,在此记录一些实践

Api: container.resolve

container.resolve 相当于 new ClassName, 但它会自动解析被注入的类, 在此注入的入口是 HogeService 的构造器[以参数形式注入]

注意: 要让一个类可注入,必须使用 @injectable 装饰器, @singleton() 可以代替 @injectable 使用 @autoInjectable 和 injectable 功能相同,但注入口处参数需要可选, 即加 ?号

import "reflect-metadata";
import { container, injectable } from "tsyringe";

// @injectable() 这里可有可无,因为没有被注入需求
class FooService {
  public constructor() {
    console.log("new FooService()");
  }
  doFoo(value: string) {
    return `${value} : Foo!`;
  }
}

@injectable() // @autoInjectable
class HogeService {
  constructor(
    private fooService: FooService
  ) {
    console.log("new HogeService()");
  }

  // constructor(
  //   // 这里不加? new AutoHogeService() 时会出错
  //   private fooService?: FooService
  // ) {
  //   console.log("new AutoHogeService()");
  // }

  doHoge(value: string) {
    return `${value} : Hoge!`;
  }
  doHogeFoo(value: string) {
    return this.fooService.doFoo(this.doHoge(value));
  }
}


//FooService 运行
console.log("---------");
const fooService = container.resolve(FooService);
console.log(fooService.doFoo("test01"));

//HogeService 运行
console.log("---------");
const hogeService = container.resolve(HogeService);
console.log(hogeService.doHogeFoo("test02"));

Api: container.register

container.register 的作用是注册一些内容以供消费

Value provider

import "reflect-metadata";
import { container, injectable, inject } from "tsyringe";

class SystemSetting {
  public settingCode: string | null = null;
  public settingName: string | null = null;
}

@injectable()
class SandboxService {
  constructor(
    @inject("systemCode") private systemCode: string,
    @inject("setting") private setting: SystemSetting
  ) {
  }

  showSystemCode() {
    console.log(`systemCode=${this.systemCode}`);
  }

  showSetting() {
    console.log(`Setting[settingCode=${this.setting.settingCode}, settingName=${this.setting.settingName}]`);
  }
}

// 注册值
container.register("systemCode", { useValue: "001" });

// 注册对象
const setting = new SystemSetting();
setting.settingCode = "010";
setting.settingName = "it";
container.register("setting", { useValue: setting });

const sandboxService = container.resolve(SandboxService);

sandboxService.showSystemCode();
sandboxService.showSetting();

Class provider

import "reflect-metadata";
import { container, injectable, inject } from "tsyringe";

@injectable()
class FooLogicImpl {

  constructor() {
    console.log("new FooLogicImpl()");
  }

  doFoo() {
    return "foo";
  }
}

@injectable()
class HogeService {

  constructor(
    @inject("FooLogic") private fooLogic: FooLogicImpl,
  ) {
    console.log("new HogeService()");
  }

  doService() {
    console.log(this.fooLogic.doFoo());
  }
}

container.register("FooLogic", { useClass: FooLogicImpl });

const hogeService = container.resolve(HogeService);
hogeService.doService();

useFactory provider

import "reflect-metadata";
import { container, DependencyContainer, injectable } from "tsyringe";

@injectable()
class BarLogic {
  constructor() {
    console.log("new BarLogic()");
  }
  doBar() {
    return "bar";
  }
}

class HogeService {
  constructor(
    private barLogic: BarLogic
  ) {
    console.log("new HogeService()");
  }
  doHoge() {
    console.log(this.barLogic.doBar());
  }
}

container.register("HogeService", {
  useFactory: (dependencyContainer: DependencyContainer) => {
    console.log("factory!")
    const barLogic = dependencyContainer.resolve(BarLogic)
    return new HogeService(barLogic);
  }
})

console.log("------")
const hogeService1 = container.resolve<HogeService>("HogeService")
hogeService1.doHoge();

console.log("------")
const hogeService2 = container.resolve<HogeService>("HogeService")
hogeService2.doHoge();
// 输出结果
// ------
// factory!
// new BarLogic()
// new HogeService()
// bar
// ------
// factory!
// new BarLogic()
// new HogeService()
// bar

instanceCachingFactory

在前面的例子中,HogeService 工厂函数在你每次请求时都会执行,但是如果使用 instanceCachingFactory,工厂函数的结果会被缓存。

// 定义代码省略...
container.register("HogeService", {
  useFactory: instanceCachingFactory<HogeService>((dependencyContainer: DependencyContainer) => {
      console.log("factory!")
      const barLogic = dependencyContainer.resolve(BarLogic)
      return new HogeService(barLogic);
  })
})

console.log("------")
const hogeService1 = container.resolve<HogeService>("HogeService")
hogeService1.doHoge();

console.log("------")
const hogeService2 = container.resolve<HogeService>("HogeService")
hogeService2.doHoge();
// 输出结果
// ------
// factory!
// new BarLogic()
// new HogeService()
// bar
// ------
// bar