本日は VContainer の小ネタ枠です。
親子関係のある LifetimeScope の依存解決の順番を確認して記事に残します。
前回記事
以下の前回記事のプロジェクトを組み合わせて利用します。
bluebirdofoz.hatenablog.com
bluebirdofoz.hatenablog.com
親子関係のあるLifetimeScopeの依存解決の順番
結論から述べると、親子関係のある LifetimeScope の依存解決は子の LifetimeScope から親に向かって探索されます。
vcontainer.hadashikick.jp
動作確認
実際に動作を確認してみました。
以下のデバッグ用のスクリプトを作成してそれぞれ projectRoot、EnqueueParent、自身の LifetimeScope いずれから IHelloWorldService のインスタンスを解決するか確認しました。
・RootParentLifetimeScope.cs(projectRootに設定したLifetimeScope)
using VContainer; using VContainer.Unity; namespace EnqueueParentSample2 { public class RootParentLifetimeScope : LifetimeScope { protected override void Configure(IContainerBuilder builder) { // DebugHelloWorldServiceをインタフェースとしてDIコンテナに登録する builder.RegisterInstance(new DebugHelloWorldService("RootParent",200)).As<IHelloWorldService>(); } } }
・EnqueueParentLifetimeScope.cs(EnqueueParentで親に指定するLifetimeScope)
using VContainer; using VContainer.Unity; namespace EnqueueParentSample2 { public class EnqueueParentLifetimeScope : LifetimeScope { protected override void Configure(IContainerBuilder builder) { // DebugHelloWorldServiceをインタフェースとしてDIコンテナに登録する builder.RegisterInstance(new DebugHelloWorldService("EnqueueParent",100)).As<IHelloWorldService>(); } } }
・GameLifetimeScope.cs(解決を行う自身のLifetimeScope)
using UnityEngine; using VContainer; using VContainer.Unity; namespace EnqueueParentSample2 { public class GameLifetimeScope : LifetimeScope { [SerializeField] private HelloScreen helloScreen; protected override void Configure(IContainerBuilder builder) { // HelloWorldServiceをインタフェースとしてDIコンテナに登録する builder.Register<HelloWorldService>(Lifetime.Singleton).As<IHelloWorldService>(); // GamePresenterをVContainerのEntryPointに登録する builder.RegisterEntryPoint<GamePresenter>(); // HelloScreenコンポーネントをDIコンテナに登録する builder.RegisterComponent<HelloScreen>(helloScreen); } } }
・IHelloWorldService.cs
namespace EnqueueParentSample2 { public interface IHelloWorldService { void Hello(); } }
・HelloWorldService.cs
namespace EnqueueParentSample2 { public class HelloWorldService : IHelloWorldService { private int count = 0; public void Hello() { count++; UnityEngine.Debug.Log($"Hello world : {count}"); } } }
・DebugHelloWorldService.cs
namespace EnqueueParentSample2 { public class DebugHelloWorldService : IHelloWorldService { private string name = ""; private int count = 0; public DebugHelloWorldService(string name, int count) { this.name = name; this.count = count; } public void Hello() { count++; UnityEngine.Debug.Log($"Hello world : {count} by {name}"); } } }
結果は以下の通り、自身の LifetimeScope で生成した IHelloWorldService のインスタンスが参照されました。
次に以下の通り、自身の LifetimeScope から IHelloWorldService のインスタンス解決を削除して試しました。
・GameLifetimeScope.cs(解決を行う自身のLifetimeScope)
using UnityEngine; using VContainer; using VContainer.Unity; namespace EnqueueParentSample2 { public class GameLifetimeScope : LifetimeScope { [SerializeField] private HelloScreen helloScreen; protected override void Configure(IContainerBuilder builder) { // GamePresenterをVContainerのEntryPointに登録する builder.RegisterEntryPoint<GamePresenter>(); // HelloScreenコンポーネントをDIコンテナに登録する builder.RegisterComponent<HelloScreen>(helloScreen); } } }
この場合は以下の通り、EnqueueParent で設定した LifetimeScope が参照されました。