#はじめに
Zenjectがイイらしいという情報を見かけたので軽く触ってみました。
#環境
Unityのバージョンは5.3.5f1, OSはWindows10です
#Zenject?
https://github.com/modesttree/zenject
Zenject is a lightweight dependency injection framework built specifically to target Unity 3D
DI (Dependency Injection, 依存性の注入) を扱うためのフレームワークだそうです。
#1. とりあえず使ってみる
##1. Zenjectのダウンロード
以下URLからダウンロードしてUnityProjectに入れます。
https://github.com/modesttree/Zenject/releases
AssetStoreからもダウンロードできます
筆者は Zenject-WithSampleGames.v4.5.unitypackage をダウンロードしました。
##2. Hello World
公式のHelloWorldを参考に実際に動かしていきます。
2. 以下のスクリプトを作成して好きなGameObjectにアタッチ。
using Zenject;
using UnityEngine;
using System.Collections;
public class TestInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.BindInstance("Hello World!");
Container.Bind<TestRunner>().NonLazy();
}
}
public class TestRunner
{
public TestRunner(string message)
{
Debug.Log(message);
}
}
3.SceneContextにTestInstaller付きのオブジェクトをアタッチ
4.Validate ( Ctrl + Shift + V )するとConsoleに以下のようなメッセージが表示されます.
あまり理解できていないのですが、InstallBindings()内にてクラス間の依存関係を定義しているみたいです。
#2. サンプルをちょっと覗いてみた
同梱のサンプルゲームに使われているコードがどのような意味を持つのか表にまとめてみました。
各コードはInstallBindings()の中で呼んでいるものとしています。
コード | 意味 | エラー例 | 備考 |
---|---|---|---|
Container.Bind<IF>().To<A>() |
インターフェースIFをクラスAが継承していることを保証する? |
A がIF を継承していないとエラー |
IFの代わりにクラスBを入れても動くみたいです |
Container.BindFactory<A, B>() |
クラスB がFactory<A> に変換可能であることを保証する? |
B がFactory<A> へ変換できないとエラー |
Factory<>はZenjectで提供されているクラス |
Container.BindInstance<int>(x).AsSingle() |
int型の変数x が変わらないことを保証する? |
1回目のBindInstance呼び出しと2回目のBindInstance呼び出しで異なるint値が渡されるとエラー | |
Container.BindAllInterfaces<A>().To<B>() |
クラスAが継承している全てのインターフェースをクラスBが継承していることを保証する? | Aが継承するインターフェースの中にをBが継承していないものがあるとエラー |
#3. Injectを使ってみた
Injectもちょっと触ってみました。 DIを行うためのものらしいです
##引数なしメソッドを呼ぶ
シーンを再生するとA()メソッドが実行されます.
using UnityEngine;
using Zenject;
public class TestInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<Hoge>().NonLazy();
}
}
public class Hoge
{
[Inject]
void A()
{
Debug.Log("A");
}
}
##引数ありメソッドを呼ぶ
WithArgumentsを使うとメソッドに引数を渡せるみたいです。
using UnityEngine;
using Zenject;
public class TestInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<Hoge>().WithArguments(810, 114514).NonLazy();
}
}
public class Hoge
{
[Inject]
void A(int x, int y)
{
Debug.Log("A : x = " + x + ", y = " + y);
}
}
#4. ITickableを使ってみた
ITickableを使うことで毎フレーム処理を実行するクラスを作ることができるらしいです。
##実際に使ってみる
シーンを再生するとTick()メソッドが毎フレーム実行されます
using UnityEngine;
using Zenject;
public class TestInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<ITickable>().To<A>().AsSingle();
}
}
class A : ITickable
{
public void Tick()
{
Debug.Log("Tick");
}
}
#5. IInitializableを使ってみた
開始時にInitialize()メソッドを実行させるためのインターフェースらしいです
実際に使ってみる
シーンを再生するとInitialize()メソッドが1度実行されます
using UnityEngine;
using Zenject;
public class TestInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<IInitializable>().To<A>();
}
}
class A : IInitializable
{
public void Initialize()
{
Debug.Log("Initialize");
}
}
##IInitializableをInjectで代用する
以下のように書くことでも同様のことができるみたいです
using UnityEngine;
using Zenject;
public class TestInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<A>().NonLazy();
}
}
class A
{
[Inject]
public void Initialize()
{
Debug.Log("Initialize");
}
}
#参考URL
GitHub - modesttree/Zenject
https://github.com/modesttree/zenject
アセットストア - Zenject Dependency Injection IOC
https://www.assetstore.unity3d.com/jp/#!/content/17758