TSyringeを動かしてみた(2)

[前回](https://qiita.com/epsilon_87_myo/items/affd143a36aee8a7bab5)の続きです。

## `scoped`を試す

DIコンテナにはインスタンスの生存期間を管理するためにスコープという概念がありますが、`TSyringe` ではどのようになっているか実際に動かして確認してみます。

まずスコープ別に４つ用意します。

```ts:scopedComponents/SingletonComponent.ts
import { singleton } from "tsyringe";

@singleton()
export default class SingletonComponent {

    constructor() {
        console.log("new SingletonComponent()")
    }
}
```


```ts:scopedComponents/ContainerComponent.ts
import { scoped, Lifecycle } from "tsyringe";

@scoped(Lifecycle.ContainerScoped)
export default class ContainerComponent {

    constructor() {
        console.log("new ContainerComponent()")
    }
}
```

```ts:scopedComponents/ResolutionComponent.ts
import { scoped, Lifecycle } from "tsyringe";

@scoped(Lifecycle.ResolutionScoped)
export default class ResolutionComponent {

    constructor() {
        console.log("new ResolutionComponent()")
    }
}
```


```ts:scopedComponents/InjectableComponent.ts
import { injectable } from "tsyringe";

@injectable()
export default class InjectableComponent {

    constructor() {
        console.log("new InjectableComponent()")
    }
}
```

これらをインジェクションしているクラスを親子で用意

```ts:ChildService.ts
import { injectable } from "tsyringe";
import SingletonComponent from "./scopedComponents/SingletonComponent";
import ContainerComponent from "./scopedComponents/ContainerComponent";
import ResolutionComponent from "./scopedComponents/ResolutionComponent";
import InjectableComponent from "./scopedComponents/InjectableComponent";

@injectable()
export default class ChildService {

    constructor(
        private singleton: SingletonComponent,
        private container: ContainerComponent,
        private resolution: ResolutionComponent,
        private injectable: InjectableComponent
    ) {
        console.log("new ChildService()")
    }
}
```

```ts:ParentService.ts
import { injectable } from "tsyringe";
import ChildService from "./ChildService";
import SingletonComponent from "./scopedComponents/SingletonComponent";
import ContainerComponent from "./scopedComponents/ContainerComponent";
import ResolutionComponent from "./scopedComponents/ResolutionComponent";
import InjectableComponent from "./scopedComponents/InjectableComponent";

@injectable()
export default class ParentService {

    constructor(
        private childService: ChildService,
        
        private singleton: SingletonComponent,
        private container: ContainerComponent,
        private resolution: ResolutionComponent,
        private injectable: InjectableComponent
    ) {
        console.log("new ParentService()")
    }
}
```

そして最後にエントリポイント

```ts:index.ts
import "reflect-metadata";
import { container } from "tsyringe";
import ParentService from "./ParentService";

console.log("-----parentService1回目")
container.resolve(ParentService);

console.log("-----parentService2回目")
container.resolve(ParentService);
```

実行結果は以下のようになりました。

```
-----parentService1回目
new SingletonComponent()
new ContainerComponent()
new ResolutionComponent()
new InjectableComponent()
new ChildService()
new InjectableComponent()
new ParentService()
-----parentService2回目
new ResolutionComponent()
new InjectableComponent()
new ChildService()
new InjectableComponent()
new ParentService()
```

- `injectable`は `ParentService`, `ChildService` 両方でインスタンス生成
- `Resolution`は `resoluve` 要求につき1個生成
- `singleton`, `Container` は２回目には含まれていないことから１つのインスタンスが再利用されている

ということがわかります。

[ドキュメント](https://github.com/microsoft/tsyringe#available-scopes)によると `Container`は`singleton`と似ていますが、子コンテナを作ったときは子コンテナで一つのインスタンスが作られるようです。

### 子コンテナを作ってみる
ということなので実際に子コンテナを作って動かしてみます。

エントリポイントのみ変更しました。
しつこく親子２回ずつ実行してみます。

```ts:index.ts
import "reflect-metadata";
import { container } from "tsyringe";
import ParentService from "./ParentService";

console.log("-----parentService1回目(親コンテナから)")
container.resolve(ParentService);

console.log("-----parentService2回目(子コンテナから)")
const childContainer1 = container.createChildContainer();
childContainer1.resolve(ParentService);

console.log("-----parentService3回目(親コンテナから)")
container.resolve(ParentService);

console.log("-----parentService4回目(子コンテナから)")
childContainer1.resolve(ParentService);
```

実行結果

```
-----parentService1回目(親コンテナから)
new SingletonComponent()
new ContainerComponent()
new ResolutionComponent()
new InjectableComponent()
new ChildService()
new InjectableComponent()
new ParentService()
-----parentService2回目(子コンテナから)
new ContainerComponent()
new ResolutionComponent()
new InjectableComponent()
new ChildService()
new InjectableComponent()
new ParentService()
-----parentService3回目(親コンテナから)
new ResolutionComponent()
new InjectableComponent()
new ChildService()
new InjectableComponent()
new ParentService()
-----parentService4回目(子コンテナから)
new ResolutionComponent()
new InjectableComponent()
new ChildService()
new InjectableComponent()
new ParentService()
```

- `new SingletonComponent()` は１回のみ
- `new ContainerComponent()` は1,2回目のみ

ということが確認できました。

続きは[こちら](https://qiita.com/epsilon_87_myo/items/28faf1fb3e95d21be63a)