Comparing to Zenject
Unityで動作する他のDIライブラリに Zenject があります。 Zenject と比較すると、VContainerは以下のような特徴があります。
- 良好なパフォーマンス
- リフレクションやアサーションなどはコンテナをビルドするフェイズですべて完了するため、オブジェクト数の増加につれてのパフォーマンス劣化が小さい。
- Zenject はシーン開始時に全ての GameObject を リフレクションで走査するなど、暗黙のうちに高コストな処理が実行されることがある。VContainerはより明示的にこのようなことを指定する。
- コードが短く実装がより読みやすくなっている
- 機能を厳選している。また、ありとあらゆるオブジェクトをDIコンテナで管理することは推奨していない。
- Zenjectでは、データとして振る舞うオブジェクトや、動的な寿命を持つViewコンポーネントを直接DIする使い方ができるようになっている。これはDIの設定が過度に複雑になっていくという欠点がある。
- VContainerでは、MonoBehaviour へ Injectするよりは MonoBehaviour を Injectすることをどちらかというと推奨している。
#
Code size (v1.3.0)#
API difference#
BasicZenject | VContainer |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
ComponentZenject | VContainer |
---|---|
|
|
|
|
|
|
|
|
|
|
#
Factory#
Factory with parameterZenject
public class Enemy{ readonly float speed;
public Enemy(float speed) { this.speed = speed; }
public class Factory : PlaceholderFactory<float, Enemy>; { }}
Container.BindFactory<float, Enemy, Enemy.Factory>();
VContainer
public class Enemy{ readonly float speed;
public Enemy(float speed) { this.speed = speed; }}
builder.RegisterFactory<float, Enemy>(speed => new Enemy(speed));
#
Factory with parameter & resolve dependency at runtimeZenject
public class Enemy{ readonly Player player; readonly float speed;
public Enemy(float speed, Player player) { this.player = player; this.speed = speed; }
public class Factory : PlaceholderFactory<float, Enemy>; { }}
Container.BindFactory<float, Enemy, Enemy.Factory>();
VContainer
public class Enemy{ readonly Player player; readonly float speed;
public Enemy(float speed, Player player) { this.player = player; this.speed = speed; }}
builder.RegisterFactory<float, Enemy>(container =>{ var player = container.Resolve<Player>(); return speed => new Enemy(speed, player);}, Lifetime.Scoped);
#
Factory with prefabZenject
public class Enemy : MonoBehaviour{ Player player;
[Inject] public void Construct(Player player) { this.player = player; }
public class Factory : PlaceholderFactory<Enemy> { }}
Container.BindFactory<Enemy, Enemy.Factory>() .FromComponentInNewPrefab(enemyPrefab);
VContainer
public class Enemy : MonoBehaviour{ Player player;
public void Construct(Player player) { this.player = player; }}
builder.RegisterFactory<Enemy>(container =>{ var player = container.Resolve<Player>(); return () => { var enemy = Instantiate(enemyPrefab); enemy.Construct(player); return enemy; };}, Lifetime.Scoped);
#
MiscZenject | VContainer |
---|---|
Signal | Not supported The central messaging pattern is useful, but depends largely on the style of the project, and the preferred implementation will vary. You can choose any implementation of UniRx.MessageBroker, UniTaskPubsub, Cysharp/MessagePipe or etc. |
Memory Pool | Not supported Currently, any Memory pool implementation is not embed. Please inject the implementation according to the purpose of the project into Factory etc. |
| Not Supported We should load Resources using LoadAsync family. You can use RegisterInstance() etc after loading the Resource. |
| Not supported Duplicate type Resolve is not recommended. You can instead use type-specific Register builder.Register(Lifetime.Scoped).WithParameter("foo", foo) |