VContainer入門(4) - MonoBehaviourのRegister

# この記事について
[前回](https://qiita.com/sakano/items/74891c424243c410ad02)に引き続きRegister関連のメソッドを紹介していきます。

今回はUnityのMonoBehaviourを登録するRegisterを紹介します。

目次ページ: [VContainer入門](https://qiita.com/sakano/items/b91e01f7fc0a946090ac)



## RegisterComponent
### 基本的な使い方
MonoBehaviourを登録するには基本的に`RegisterComponent`を使います。[^1]

すでに存在するインスタンスを登録する点では`RegisterInstance`と同じです。
`RegisterInstance`との違いは、登録したインスタンスに対してInjectされることです。
Injectされるタイミングは`IObjectResolver`が生成された直後です。

```cs:登録する
var testMonoBehaviour = GetComponent<TestMonoBehaviour>();
builder.RegisterComponent(testMonoBehaviour);
```
```cs:受け取る
[Inject]
public Constructor(TestMonoBehaviour testMonoBehaviour) { }
```




## RegisterComponentInHierarchy
### 基本的な使い方
`RegisterComponent`では登録するMonoBehaviourのインスタンスを指定していました。
それに対して`RegisterComponentInHierarchy`では登録する型だけを指定します。
その型のMonoBehaviourを、LifetimeScopeが配置されたシーン全体から自動的に探索します。

登録するインスタンスに対してInjectされるのは`RegisterComponent`と同じです。

```cs:登録する
// シーン中のどこかに存在するTestMonoBehaviourが登録される
builder.RegisterComponentInHierarchy<TestMonoBehaviour>();
```
```cs:受け取る
[Inject]
public Constructor(TestMonoBehaviour testMonoBehaviour) { }
```

### 探索先を指定する
登録するMonoBehaviourをシーン全体ではなく指定した範囲から探すように指定できます。

`UnderTransform`でtransformを渡すとそのTransformの中から探索されます。
探される範囲は指定したTransformとその子孫です。

```cs:登録する
builder.RegisterComponentInHierarchy<TestMonoBehaviour>().UnderTransform(transform);
```

また、transformを直接指定する代わりにtransformを返すデリゲートを渡すこともできます。

```cs:登録する
builder.RegisterComponentInHierarchy<TestMonoBehaviour>().UnderTransform(() => transform);
```




## RegisterComponentOnNewGameObject
### 基本的な使い方
`RegisterComponentOnNewGameObject`では`RegisterComponentInHierarchy`と同じくMonoBehaviourの型を登録します。

`RegisterComponentInHierarchy`ではすでに存在するMonoBehaviourを探して登録していました。
対して`RegisterComponentOnNewGameObject`ではresolveする時に新しく生成します。
具体的には新しいGameObjectを生成してそこに指定されたMonoBehaviourをアタッチします。

```cs:登録する
builder.RegisterComponentOnNewGameObject<TestMonoBehaviour>(Lifetime.Singleton);
```
```cs:受け取る
// 新しいGameObjectにアタッチされたTestMonoBehaviourが渡される
[Inject]
public Constructor(TestMonoBehaviour testMonoBehaviour) { }
```

### 生成先を指定する
新しいGameObjectを生成するときの親となるtransformを`UnderTransform`で指定できます。

```cs:登録する
builder.RegisterComponentOnNewGameObject<TestMonoBehaviour>(Lifetime.Singleton).UnderTransform(transform);
```

### GameObjectの名前を指定する
生成されるGameObjectの名前を指定できます。
指定しない場合は登録した型の名前になります。

```cs:登録する
builder.RegisterComponentOnNewGameObject<TestMonoBehaviour>(Lifetime.Singleton, "newGameObject");
```




## RegisterComponentInNewPrefab
`RegisterComponentOnNewGameObject`では新しいGameObjectを生成してそこにアタッチしていました。

`RegisterComponentInNewPrefab`を使うとどのようなGameObjectを生成するかプレハブで指定できます。

```cs:登録する
TestMonoBehaviour prefab;
builder.RegisterComponentInNewPrefab<TestMonoBehaviour>(prefab, Lifetime.Singleton);
```
```cs:受け取る
// 生成されたプレハブの中のTestMonoBehaviourが渡される
[Inject]
public Constructor(TestMonoBehaviour testMonoBehaviour) { }
```

### 生成先を指定する
プレハブを生成するときの親となるtransformを`UnderTransform`で指定できます。

```cs:登録する
builder.RegisterComponentInNewPrefab<TestMonoBehaviour>(prefab, Lifetime.Singleton).UnderTransform(transform);
```




## UseComponents
`UseComponents`を使うと`UnderTransform`の設定をまとめてできます。

```cs:登録する
builder.UseComponents(transform, componentsBuilder =>
{
    // builder.RegisterComponentInHierarchy<TestMonoBehaviour>().UnderTransform(transform); と同じ
    componentsBuilder.AddInHierarchy<TestMonoBehaviour>();

    // builder.RegisterComponentOnNewGameObject<TestMonoBehaviour2>(Lifetime.Singleton).UnderTransform(transform); と同じ
    componentsBuilder.AddOnNewGameObject<TestMonoBehaviour2>(Lifetime.Singleton);

    // builder.RegisterComponentInNewPrefab(prefab, Lifetime.Singleton).UnderTransform(transform); と同じ
    componentsBuilder.AddInNewPrefab(prefab, Lifetime.Singleton);
});
```

[^1]: v1.8.0からMonoBehaviour以外のScriptableObjectなどでも使えるようです。