facebook twitter hatena line email

「Unity/DIフレームワーク/Extenject/基本」の版間の差分

提供: 初心者エンジニアの簡易メモ
移動: 案内検索
("Found multiple matches when only one was expected for type"エラーが出る場合)
(BindInterfacesToの場合)
 
(同じ利用者による、間の29版が非表示)
行1: 行1:
  
 
==Extenjectとは==
 
==Extenjectとは==
UnityのDIフレームワーク。Zenjectは、作者が前務めてた会社で作られたDIフレームワークの名前。
+
UnityのDI(依存性の注入)フレームワーク。Zenjectは、作者が前務めてた会社で作られたDIフレームワークの名前。
  
 
==ダウンロード==
 
==ダウンロード==
unityのassetstore
+
===unityのassetstore===
 
https://assetstore.unity.com/packages/tools/utilities/extenject-dependency-injection-ioc-157735
 
https://assetstore.unity.com/packages/tools/utilities/extenject-dependency-injection-ioc-157735
  
 
公式
 
公式
 
https://github.com/modesttree/Zenject/releases
 
https://github.com/modesttree/Zenject/releases
 +
 +
====インストール確認====
 +
Assets/Plugins/Zenjectにデータが有ればOK
 +
 +
===PackageManagerでインストール===
 +
#Unityメインメニュー/Window/PackageManager/右上の+
 +
#Add package from git URL
 +
 +
https://github.com/svermeulen/Extenject.git?path=/UnityProject/Assets/Plugins/Zenject
 +
 +
====インストール確認====
 +
Packages/manifest.jsonに、以下のようにextenjectが追加されていればOK
 +
"com.svermeulen.extenject": "https://github.com/svermeulen/Extenject.git?path=/UnityProject/Assets/Plugins/Zenject",
 +
 +
====起動時のエラー====
 +
詳細
 +
Asset Packages/com.svermeulen.extenject/OptionalExtras/Async has no meta file, but it's in an immutable folder. The asset will be ignored.
 +
*2020.2や2020.3だから起こるのかも、ほかバージョンにすれば良いかもとあるかも?
 +
*確認すると、UnityPackages/com.svermeulen.extenject/OptionalExtras/Asyncにmetaがない模様・・。
 +
*UnityAssetstore側からDLすると直った。
  
 
==サンプル==
 
==サンプル==
行31: 行51:
 
}
 
}
 
</pre>
 
</pre>
CarView.cs
+
SampleMain.cs
 
<pre>
 
<pre>
 
using UnityEngine;
 
using UnityEngine;
 
using Zenject;
 
using Zenject;
public class CarView : MonoBehaviour
+
public class SampleMain : MonoBehaviour
 
{
 
{
 
     [Inject] ILogic _logic;
 
     [Inject] ILogic _logic;
行64: 行84:
  
 
#Scene選択
 
#Scene選択
#Hierarchyに、Create EmptyでGameObjectを作り、CarViewの名前に変更し、CarView.csを、AddCompornentする。
+
#Hierarchyに、Create EmptyでGameObjectを作り、SampleMainの名前に変更し、SampleMain.csを、AddCompornentする。
 
#Hierarchyに、Create EmptyでGameObjectを作り、HogeLogicInstallerの名前に変更し、HogeLogicInstaller.csを、AddCompornentする。
 
#Hierarchyに、Create EmptyでGameObjectを作り、HogeLogicInstallerの名前に変更し、HogeLogicInstaller.csを、AddCompornentする。
 
#Hierarchyから右クリックし、Zenject/SceneContextを追加
 
#Hierarchyから右クリックし、Zenject/SceneContextを追加
行77: 行97:
  
 
参考:https://github.com/modesttree/Zenject
 
参考:https://github.com/modesttree/Zenject
 +
 +
==引数に入れるサンプル==
 +
<pre>
 +
public class SampleMain : MonoBehaviour
 +
{
 +
    [Inject]
 +
    void StartInject(ILogic _logic
 +
        )
 +
    {
 +
        if (_logic != null)
 +
        {
 +
            _logic.Exec();
 +
        }
 +
    }
 +
}
 +
</pre>
 +
StartInject()とか適当なメソッドを作って、[Inject]をつけると、勝手にこのメソッドが起動して、実行される。
  
 
==AsSingleとAsCachedとAsTransient==
 
==AsSingleとAsCachedとAsTransient==
行85: 行122:
 
===AsCachedについて===
 
===AsCachedについて===
 
<pre>
 
<pre>
        Container
+
Container
            .Bind<ILogic>()
+
.Bind<ILogic>()
            .To<HogeLogic>()
+
.To<HogeLogic>()
            .AsCached(); // キャッシュする
+
.AsCached(); // キャッシュする
        Container
+
Container
            .Unbind<HogeLogic>(); // キャッシュを削除
+
.Unbind<ILogic>(); // キャッシュを削除
        Container
+
Container
            .Bind<ILogic>()
+
.Bind<ILogic>()
            .To<HogeLogic>()
+
.To<HogeLogic>()
            .AsCached(); // キャッシュする
+
.AsCached(); // キャッシュする
        Container
+
Container
            .Resolve<HogeLogic>()
+
.Resolve<HogeLogic>()
            .Exec(); // 実行
+
.Exec(); // 実行
 
</pre>
 
</pre>
 
キャッシュを削除して、再度Bindして実行
 
キャッシュを削除して、再度Bindして実行
行103: 行140:
 
===インスタンスを入れる場合===
 
===インスタンスを入れる場合===
 
<pre>
 
<pre>
        Container
+
Container
            .Bind<ILogic>()
+
.Bind<ILogic>()
            .FromInstance(new HogeLogic())
+
.FromInstance(new HogeLogic())
            .AsSingle();
+
.AsSingle();
 
</pre>
 
</pre>
  
 
参考:https://light11.hatenadiary.com/entry/2019/02/20/234834
 
参考:https://light11.hatenadiary.com/entry/2019/02/20/234834
 +
 +
==Bind処理いろいろ==
 +
IfNotBound()を使えば、既に同じintarfaceのインスタンスを作っていれば、作らない。
 +
 +
NonLazy()を使えば、最初にインスタンスが作られる。
 +
 +
参考:https://light11.hatenadiary.com/entry/2019/02/22/005845#WithId
 +
 
==エラーについて==
 
==エラーについて==
 
こんな感じのエラーのときは
 
こんな感じのエラーのときは
行139: 行184:
 
=="Found multiple matches when only one was expected for type"エラーが出る場合==
 
=="Found multiple matches when only one was expected for type"エラーが出る場合==
 
エラー詳細
 
エラー詳細
  ZenjectException: Found multiple matches when only one was expected for type 'ILogic' while building object with type 'CarView'. Object graph:
+
  ZenjectException: Found multiple matches when only one was expected for type 'ILogic' while building object with type 'SampleMain'. Object graph:
  CarView
+
  SampleMain
 
ILogicに入れるInstallerが2つ以上あるので、このエラーが起こってる。
 
ILogicに入れるInstallerが2つ以上あるので、このエラーが起こってる。
  
対応方法は、Installerを1つにするか、.WithId()を使うなどをつける。
+
対応方法は、
 +
#Installerを1つにするか。
 +
#WithId()を使うなどをつけるか。
 +
#Unbind()して、キャッシュを削除するか。
 +
#IfNotBound()って、同じintarfaceのインスタンスを無視するか。
 +
 
 +
===WithId()を使うなどをつける方法===
 
例:
 
例:
 
<pre>
 
<pre>
行158: 行209:
 
</pre>
 
</pre>
 
参考:https://light11.hatenadiary.com/entry/2019/02/22/005845#WithId
 
参考:https://light11.hatenadiary.com/entry/2019/02/22/005845#WithId
 +
 +
===Unbindでキャッシュを削除する方法===
 +
初回のBindのキャッシュを削除
 +
<pre>
 +
Container
 +
    .Unbind<ILogic>();
 +
</pre>
 +
 +
===IfNotBound()って、同じintarfaceのインスタンスを無視する方法===
 +
<pre>
 +
Container
 +
    .Bind<ILogic>()
 +
    .To<PiyoLogic>()
 +
    .AsCached();
 +
    .IfNotBound();
 +
</pre>
 +
 +
===Interfaceがない場合===
 +
Toを、同名で、つけても動くが、Toは、つけなくてもよい。
 +
<pre>
 +
Container
 +
      .Bind<PiyoLogic>()
 +
      // .To<PiyoLogic>()
 +
      .AsTransient();
 +
</pre>
 +
 +
==BindInterfacesAndSelfToの場合==
 +
すべてのinterfaceと、クラスをbindしてる。
 +
ライフサイクルがinterfaceについてれば、それらもつく。
 +
<pre>
 +
Container.BindInterfacesAndSelfTo<PiyoLogic>();
 +
</pre>
 +
 +
[[Unity/DIフレームワーク/Extenject/非MonoBehavior]] [ショートカット]
 +
 +
==BindInterfacesToの場合==
 +
すべてのinterfaceがついてくる
 +
 +
<pre>
 +
Container.BindInterfacesTo<PiyoLogic>();
 +
</pre>
 +
 +
参考:https://dev.to/enpel/zenject-bind-4m2a
  
 
==参考==
 
==参考==
行165: 行259:
 
依存性注入とは?と、なっているのでZenject(Extenject)を入門
 
依存性注入とは?と、なっているのでZenject(Extenject)を入門
 
https://qiita.com/4_mio_11/items/4306732bc47780802b74
 
https://qiita.com/4_mio_11/items/4306732bc47780802b74
 +
 +
Zenject READMEの日本語訳
 +
https://qiita.com/rookx/items/3510467a2b57d3e39bc1

2023年11月15日 (水) 12:56時点における最新版

Extenjectとは

UnityのDI(依存性の注入)フレームワーク。Zenjectは、作者が前務めてた会社で作られたDIフレームワークの名前。

ダウンロード

unityのassetstore

https://assetstore.unity.com/packages/tools/utilities/extenject-dependency-injection-ioc-157735

公式 https://github.com/modesttree/Zenject/releases

インストール確認

Assets/Plugins/Zenjectにデータが有ればOK

PackageManagerでインストール

  1. Unityメインメニュー/Window/PackageManager/右上の+
  2. Add package from git URL

https://github.com/svermeulen/Extenject.git?path=/UnityProject/Assets/Plugins/Zenject

インストール確認

Packages/manifest.jsonに、以下のようにextenjectが追加されていればOK

"com.svermeulen.extenject": "https://github.com/svermeulen/Extenject.git?path=/UnityProject/Assets/Plugins/Zenject",

起動時のエラー

詳細

Asset Packages/com.svermeulen.extenject/OptionalExtras/Async has no meta file, but it's in an immutable folder. The asset will be ignored.
  • 2020.2や2020.3だから起こるのかも、ほかバージョンにすれば良いかもとあるかも?
  • 確認すると、UnityPackages/com.svermeulen.extenject/OptionalExtras/Asyncにmetaがない模様・・。
  • UnityAssetstore側からDLすると直った。

サンプル

Installerからデータを入れて、[Inject]部分に入る。

ILogic.cs

public interface ILogic
{
    bool Exec();
}

HogeLogic.cs

public class HogeLogic : ILogic
{
    public bool Exec()
    {
        Debug.Log("HogeLogc Exec");
        return true;
    }
}

SampleMain.cs

using UnityEngine;
using Zenject;
public class SampleMain : MonoBehaviour
{
    [Inject] ILogic _logic;
    void Start()
    {
        if (_logic != null)
        {
            _logic.Exec();
        }
    }
}

HogeLogicInstaller.cs

using Zenject;
public class HogeLogicInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container
            .Bind<ILogic>()
            .To<HogeLogic>()
            .AsCached();
    }
}
  1. Scene選択
  2. Hierarchyに、Create EmptyでGameObjectを作り、SampleMainの名前に変更し、SampleMain.csを、AddCompornentする。
  3. Hierarchyに、Create EmptyでGameObjectを作り、HogeLogicInstallerの名前に変更し、HogeLogicInstaller.csを、AddCompornentする。
  4. Hierarchyから右クリックし、Zenject/SceneContextを追加
  5. 作成した、SceneContextを選択し、InspectorのMonoInstallersに、HogeLogicInstallerのGameObjectをドラッグする。
  6. 実行するとCarのHogeLogicが実行できる

installer<TDerived>エラー

public class HogeLogicInstaller : Installer<HogeLogic>の部分で、 以下エラーが発生。

unity はジェネリック型またはメソッド installer<TDerived> 内で型パラメーター'TDerived として使用できません。

InstallBindingsメソッドを実行するクラスの継承元を : Installer<HogeLogic> などから MonoInstaller へ

参考:https://github.com/modesttree/Zenject

引数に入れるサンプル

public class SampleMain : MonoBehaviour
{
    [Inject]
    void StartInject(ILogic _logic
        )
    {
        if (_logic != null)
        {
            _logic.Exec();
        }
    }
}

StartInject()とか適当なメソッドを作って、[Inject]をつけると、勝手にこのメソッドが起動して、実行される。

AsSingleとAsCachedとAsTransient

  • AsSingle:インスタンスは一つで、シングルトンと同じ。
  • AsCached:インスタンスを、キャッシュする。UnBindで破棄される。
  • AsTransient:インスタンスは毎回作る。

AsCachedについて

Container
	.Bind<ILogic>()
	.To<HogeLogic>()
	.AsCached(); // キャッシュする
Container
	.Unbind<ILogic>(); // キャッシュを削除
Container
	.Bind<ILogic>()
	.To<HogeLogic>()
	.AsCached(); // キャッシュする
Container
	.Resolve<HogeLogic>()
	.Exec(); // 実行

キャッシュを削除して、再度Bindして実行

インスタンスを入れる場合

Container
	.Bind<ILogic>()
	.FromInstance(new HogeLogic())
	.AsSingle();

参考:https://light11.hatenadiary.com/entry/2019/02/20/234834

Bind処理いろいろ

IfNotBound()を使えば、既に同じintarfaceのインスタンスを作っていれば、作らない。

NonLazy()を使えば、最初にインスタンスが作られる。

参考:https://light11.hatenadiary.com/entry/2019/02/22/005845#WithId

エラーについて

こんな感じのエラーのときは

while building object with type Object graph:

Installerに、Containerがたりないので、以下のような感じで、追加すれば良い。

Container
    .Bind<IHogeLogic>()
    .FromInstance(new HogeLogic())
    .AsCached()
    .IfNotBound();

参考:https://adarapata.hatenablog.com/entry/2019/01/02/000848

インストーラーからコンテナを削除したときのエラー

Container
    .Bind<IHogeLogic>()
    .FromInstance(new HogeLogic())
    .AsCached()
    .IfNotBound();

を削除したときは、以下がエラーとして出てくる。

ZenjectException: Unable to resolve 'IHogeLogic' while building object with type 'HogeLogicInstaller'. Object graph:
HogeLogicInstaller

"Found multiple matches when only one was expected for type"エラーが出る場合

エラー詳細

ZenjectException: Found multiple matches when only one was expected for type 'ILogic' while building object with type 'SampleMain'. Object graph:
SampleMain

ILogicに入れるInstallerが2つ以上あるので、このエラーが起こってる。

対応方法は、

  1. Installerを1つにするか。
  2. WithId()を使うなどをつけるか。
  3. Unbind()して、キャッシュを削除するか。
  4. IfNotBound()って、同じintarfaceのインスタンスを無視するか。

WithId()を使うなどをつける方法

例:

Container
    .Bind<ILogic>()
    .WithId("exampleId")
    .To<PiyoLogic>()
    .AsSingle();
- [Inject] ILogic _logic;
+ [Inject(Id = "exampleId")] ILogic _logic;

参考:https://light11.hatenadiary.com/entry/2019/02/22/005845#WithId

Unbindでキャッシュを削除する方法

初回のBindのキャッシュを削除

Container
    .Unbind<ILogic>();

IfNotBound()って、同じintarfaceのインスタンスを無視する方法

Container
    .Bind<ILogic>()
    .To<PiyoLogic>()
    .AsCached();
    .IfNotBound();

Interfaceがない場合

Toを、同名で、つけても動くが、Toは、つけなくてもよい。

Container
      .Bind<PiyoLogic>()
      // .To<PiyoLogic>()
      .AsTransient();

BindInterfacesAndSelfToの場合

すべてのinterfaceと、クラスをbindしてる。 ライフサイクルがinterfaceについてれば、それらもつく。

Container.BindInterfacesAndSelfTo<PiyoLogic>();

Unity/DIフレームワーク/Extenject/非MonoBehavior [ショートカット]

BindInterfacesToの場合

すべてのinterfaceがついてくる

Container.BindInterfacesTo<PiyoLogic>();

参考:https://dev.to/enpel/zenject-bind-4m2a

参考

DIフレームワーク「Extenject(Zenject)」についてまとめました https://www.theylive.co.jp/unitydi%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFextenjectzenject%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%BE%E3%81%A8/

依存性注入とは?と、なっているのでZenject(Extenject)を入門 https://qiita.com/4_mio_11/items/4306732bc47780802b74

Zenject READMEの日本語訳 https://qiita.com/rookx/items/3510467a2b57d3e39bc1