VContainerことはじめ
MonoBehaviourが神クラスになりがちなのがよくない
ViewはMonoBehaviourになることが多いが、Viewは寿命が不安定なのでここで制御したくない
LifetimeScope を継承したコンポーネントを作り、シーンに置きます。これが1つのコンテナ(1つのスコープ)を表現します。
LifetimeScopeのメソッドをオーバライドして、依存関係を管理したいオブジェクトを登録していきます。(これがいわゆる Composition Root)
シーンをプレイすると、LifetimeScope は自動的にコンテナをつくり、独自の Player Loop System のスケジュールを始めます。
ZenjectのSceneContextとMonoInstallerまとめたような感じ?
VContainer は、名前が「LifetimeScope」で終わる C# スクリプトのファイルに対して自動的にテンプレートを適用します。
エントリポイントをMonoBehaviourにしなくてもいい
ITickableを実装したクラスを定義して、それをLifetimeScopeでエントリポイントに指定すれば、Tick()が定期実行される
MonoBehaviourではメソッドインジェクションを使う
Inject属性を付けても自動的には呼び出されない
いくつかの登録方法が用意されているので、注入されるように設定する必要がある
静的なGameObjectは事前にインスペクタから追加
動的生成されるGameObjectは通常のInstantiateではなくIObjectResolver.Instantiateで生成
ZenjectのSceneContextのように自動的に注入するのではない?
このあたり思想が違う?
処理の流れについて
ZenjectのProjectContextに相当する?
VContainerSettings を作成すると、自動的に プロジェクトの Preload Assets に登録されます。
実際にVContainerを使う際はLifetimeScopeを使うことが多いです。LifetimeScopeはIContainerBuilderとIObjectResolverをいい感じに管理してくれるクラスです。
ContainerBuilderにクラスを登録
ContainerBuilderからObjectResolverを生成
ObjectResolverを破棄すると、生成されたクラスも破棄される
シーンに依存しない場合、VContainer.Unity以下はいらないかも
LifetimeScope.Configure()に相当する処理をどこかでやりたい
親スコープが存在しないとき、LifetimeScope.Build()でContainerBuilderを新しく生成してConfigure()に渡している
生成時にApplicationOriginとDiagnosticsを渡している
ApplicationOriginはRegisterComponentInHierarchy()でLifetimeScopeの存在するシーンを参照するために使われている
RegisterComponentInHierarchy()を使わないならnullでもいい
DiagnosticsはLifetimeScopeと同様に渡しておきたい
scopeNameは $"{name} ({gameObject.GetInstanceID()})"で与えられる
nameはGameObjectの名前
ContainerBuilderを直接生成する場合、Diagnosticsで表示したい名前を適当に与えればよさそう
多分これでいいはず
ContainerBuilderを生成
ContainerBuilderに生成ルールを登録
ContainerBuilder.Build()でコンテナを取得
コンテナからエントリポイントのインスタンスを取得
子スコープはContainer.CreateScope(Action<IContainerBuilder> installation)で作れる
親スコープで生成されたIContainerBuilder受け取って生成ルールを登録するActionを渡す
MonoBehaviourを登録するならContainerBuilderUnityExtensionsが必要なので、VContainer.Unityは除外できない
単にMonobehaviourを渡したいだけならファクトリの引数にすればいいので、ContainerBuilderUnityExtensionsは不要
雑にVContainer.Unityを除外するとVContainerSettingsに依存しているDiagnosticsが使えなくなる
DiagnosticsはContainer.Resolveの実行時にTraceResolveしているので、LifetimeScopeを使わない場合でも活用できる
VContainer.Unityを除外したいならVContainerSettingsをDiagnosticsのアセンブリに入れればよさそうだが、そこまでしてVContainer.Unityを除外するモチベーションもない
UniTaskやUniRxとの連携は、LifetimeScopeのエントリポイントを使わない場合は無効でよさそう