Doinject 1.1.1 Help

Doinject をはじめよう

Unity Package Manager でインストール

Unity Package Manager からインストールすることができます。

MewCore のインストール

まず、依存ライブラリとなる、MewCore パッケージをインストールしてください。

  1. Unity のメニューから Window > Package Manager を選択します。

  2. + ボタンをクリックし、 Add package from git URL... を選択します。

  3. 以下を入力し、 Add をクリックします。

    https://github.com/mewlist/MewCore.git
    git@github.com:mewlist/MewCore.git

Doinject のインストール

次に、Doinject パッケージをインストールします。

  1. Unity のメニューから Window > Package Manager を選択します。

  2. + ボタンをクリックし、 Add package from git URL... を選択します。

  3. 以下を入力し、 Add をクリックします。

    https://github.com/mewlist/Doinject.git
    git@github.com:mewlist/Doinject.git

エントリポイントを決める

最初にすべきことは、DIフレームワークを適用したいシーンを開き、ヒエラルキに SceneContext コンポーネントを配置することです。

ヒエラルキビューで右クリックし、 Doinject > Create Scene Context > メニューを選択します。

ContextMenu

配置されたシーンコンテクスト

SceneContext.png

これで、このシーンは DI フレームワークの実行環境として機能するようになりました。 試しに一度再生してみてください。

SceneContextCreated.png

シーンが再生されると、このように各種ローダーが生成されます。

初めてのインジェクション

DIコンテナにインスタンスを登録して、インジェクションを行ってみましょう。 インスタンスの登録(バインディングと言います)はインストーラというコンポーネントから行います。

注入ポイントについて

DIコンテナに登録された型を、特定のインスタンスへ注入するためには、以下方法があります
  • コンストラクタインジェクション

  • メソッドインジェクション

  • フィールドインジェクション

  • プロパティインジェクション

コンストラクタインジェクションは、DIコンテナを通じてインスタンスを生成する際に自動的に行われます。 メソッドインジェクションは、[Inject] 属性をつけたメソッドを呼び出すことで行われます。 プロパティインジェクション・フィールドインジェクションは、[Inject] 属性をつけたフィールド・プロパティに対してインスタンスを注入します。

MonoBehaviour を継承したコンポーネントの場合、コンストラクタインジェクションは使えません。 コンポーネントの生成は、Unity が行うため、明示的にコンストラクタを呼び出せないためです。 そのため、メソッドインジェクション・フィールドインジェクション・プロパティインジェクションを使う必要があります。

コンストラクタインジェクション

class SomeClass { // SomeClass の生成時に、自動的に SomeDependency が注入されます public SomeClass(SomeDependency dependency) { ... } }

メソッドインジェクション

class SomeClass { // [Inject] 属性をつけたメソッドは、インスタンスの生成後、DIコンテナによって呼び出され SomeDependency を引数に渡します [Inject] public InjectMethod(SomeDependency dependency) { ... } }

OnInjected() コールバックについて

[OnInjected] 属性が付与されたメソッドは(引数なし・public) は、 インスタンスの注入が完了したタイミングで、自動的に呼び出されます。 Task, ValueTask の戻り値を持つ非同期関数であっても問題ありません。

特に、MonoBehaviour を継承したコンポーネントの場合、Awake や Start などのライフサイクルメソッドと、 インジェクションが行われるタイミングが前後する可能性があります。 [OnInjected] コールバックは、インジェクションが完了した次のフレームで呼び出されるようになっているため、 初期化順を安定化させる目的で使用できます。

class SomeClass { public SomeClass(SomeDependency dependency) { ... } // インスタンスの注入が完了したタイミングで、自動的に呼び出されます [OnInjected] public void OnInjected() { ... } }

インストーラスクリプトの作成

インストーラは、 Doinject メニューから作成することができます。Project ビューで右クリックし、 Create > Doinject > Component Binding Installer C# Script を選択することで、 インストーラスクリプトが作成されます。

SceneContext

CustomComponentBindingInstallerScript.cs という名前でスクリプトを作成した場合、以下のようなスクリプトが作成されます。

using Doinject; public class CustomComponentBindingInstallerScript : BindingInstallerComponent { public override void Install(DIContainer container) { // Bind your dependencies here } }

また、動作を確認するため、DIコンテナに登録するオブジェクトと注入先のスクリプトを以下のように作成します。

プレイヤーオブジェクト

using System; using UnityEngine; [Serializable] public class Player { [SerializeField] public string name; public Player(string name) { this.name = name; } }

注入先スクリプト

using Doinject; using UnityEngine; public class InjectTargetScript : MonoBehaviour, IInjectableComponent { [SerializeField] private Player player; [Inject] public void Construct(Player player) { this.player = player; } }

Player オブジェクトのインスタンスがInjectTargetScript.Construct() を通じて インジェクトされることがゴールとなります。

では、インストーラーにバインディングを記述していきましょう。 バインディングは、Install メソッド内で行います。

public override void Install(DIContainer container) { container .Bind<Player>() .Args("Novice Player") .AsSingleton(); }

.Bind<Player>() は、Player クラスをコンテナを通じて提供してもらうための宣言です。 .Args("Novice Player") は、Player クラスのコンストラクタにわたす引数となります。 .AsSingleton() は、コンテナを通じて提供される Player オブジェクトがシングルトンであることを示します。

バインド記述は、此のように Fluent Interface を通じて行います。 記述の仕方により、ファクトリとして振る舞ったり、インターフェースを介してインスタンスを提供してもらうようにしたりと柔軟な振る舞いの定義ができます。

これで、コンテクスト内で唯一となる Player オブジェクトが、DIコンテナに登録されました。

最後に、インストーラーをシーンに配置しましょう。

Installer placed on scene

コンポーネントインストーラーは、基本的にシーンのどこに置いてあっても機能します。 また、複数の異なるインストーラーがあっても構いません。 わかりやすさのため、エントリポイントの下に置くなどルールを決めておくのが良いでしょう。

動作確認

先程つくった、InjectTargetScript コンポーネントを、シーンに配置しましょう。

Inject target placed on scene

では、シーンを再生してみます。

Inject target injected

Player の Name に "Novice Player" という文字列が設定されていることが確認できます。

Player のコンストラクタに Args で指定した引数が渡り(コンストラクタインジェクション)、 さらに、InjectTargetScript の Construct メソッドに Player オブジェクトが渡ったことが確認できました(メソッドインジェクション)。

補足

シーン全体に配置されたオブジェクトは、すべてシーンコンテクストに包まれます。
  • シーンコンテクストは、生成時に、自身のコンテクストに属するインストーラーを探し、それらの定義に従ってバインディングを行います。

  • すべてのインストーラーのバインディングが完了すると、DIContainer は自身が扱うべき型とインスタンス解決方法を知っている状態となります。

  • その後、シーンコンテクストは、シーン内のすべてのゲームオブジェクトを探索し、IInjectableComponent を実装したコンポーネントを探します。

  • IInjectableComponent を実装したコンポーネントが見つかったら、そのコンポーネントの [Inject] 属性が指定されたメソッドの引数と型が一致するインスタンスを渡すよう呼び出します。

  • シーンコンテクストは、シーンのライフサイクルに合わせて生成され、シーンが破棄されると同時に、コンテナが抱えるインスタンスとともに破棄されます。

Last modified: 26 July 2025