「Unity/DIフレームワーク/Extenject/基本」の版間の差分
(→"Found multiple matches when only one was expected for type"エラーが出る場合) |
(→BindInterfacesToの場合) |
||
(同じ利用者による、間の28版が非表示) | |||
行1: | 行1: | ||
==Extenjectとは== | ==Extenjectとは== | ||
− | + | 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> | ||
− | + | SampleMain.cs | |
<pre> | <pre> | ||
using UnityEngine; | using UnityEngine; | ||
using Zenject; | using Zenject; | ||
− | public class | + | public class SampleMain : MonoBehaviour |
{ | { | ||
[Inject] ILogic _logic; | [Inject] ILogic _logic; | ||
行64: | 行84: | ||
#Scene選択 | #Scene選択 | ||
− | #Hierarchyに、Create | + | #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 | |
− | + | .Bind<ILogic>() | |
− | + | .To<HogeLogic>() | |
− | + | .AsCached(); // キャッシュする | |
− | + | Container | |
− | + | .Unbind<ILogic>(); // キャッシュを削除 | |
− | + | Container | |
− | + | .Bind<ILogic>() | |
− | + | .To<HogeLogic>() | |
− | + | .AsCached(); // キャッシュする | |
− | + | Container | |
− | + | .Resolve<HogeLogic>() | |
− | + | .Exec(); // 実行 | |
</pre> | </pre> | ||
キャッシュを削除して、再度Bindして実行 | キャッシュを削除して、再度Bindして実行 | ||
行103: | 行140: | ||
===インスタンスを入れる場合=== | ===インスタンスを入れる場合=== | ||
<pre> | <pre> | ||
− | + | Container | |
− | + | .Bind<ILogic>() | |
− | + | .FromInstance(new HogeLogic()) | |
− | + | .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 ' | + | ZenjectException: Found multiple matches when only one was expected for type 'ILogic' while building object with type 'SampleMain'. Object graph: |
− | + | SampleMain | |
ILogicに入れるInstallerが2つ以上あるので、このエラーが起こってる。 | ILogicに入れるInstallerが2つ以上あるので、このエラーが起こってる。 | ||
− | + | 対応方法は、 | |
+ | #Installerを1つにするか。 | ||
+ | #WithId()を使うなどをつけるか。 | ||
+ | #Unbind()して、キャッシュを削除するか。 | ||
+ | #IfNotBound()って、同じintarfaceのインスタンスを無視するか。 | ||
+ | ===WithId()を使うなどをつける方法=== | ||
例: | 例: | ||
<pre> | <pre> | ||
行159: | 行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 | ||
==参考== | ==参考== | ||
行166: | 行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でインストール
- 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すると直った。
サンプル
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(); } }
- Scene選択
- Hierarchyに、Create EmptyでGameObjectを作り、SampleMainの名前に変更し、SampleMain.csを、AddCompornentする。
- Hierarchyに、Create EmptyでGameObjectを作り、HogeLogicInstallerの名前に変更し、HogeLogicInstaller.csを、AddCompornentする。
- Hierarchyから右クリックし、Zenject/SceneContextを追加
- 作成した、SceneContextを選択し、InspectorのMonoInstallersに、HogeLogicInstallerのGameObjectをドラッグする。
- 実行すると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つ以上あるので、このエラーが起こってる。
対応方法は、
- Installerを1つにするか。
- WithId()を使うなどをつけるか。
- Unbind()して、キャッシュを削除するか。
- 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