젠젝트는 '제어의 역전'(Inversion Of Control) 이라는 중요한 설계 원칙을 기반으로 한다.
젠젝트의 핵심은 클래스가 자신의 종속성을 찾는데 책임이 없어야 한다는 것이다.
이는 종속성 주입에 대해서 완전히 분리된 코드를 작성할 수 있게 해주기 때문에 매우 훌륭하다.
이렇게 A는 B를 모르고, B는 A를 모르게 분리하는 것은 여러모로 유익하지만
만약 분리된 A와 B가 통신해야하는 상황이 온다면 어떻게 해야할까?
이 경우 A와 B가 상호작용하는 객체를 도입하여 해결할 수 있다.
var eventManager = new EventManager();
var a = new A();
var b = new B();
eventManager.Listen(b.DoSomething());
젠젝트에서는 이러한 객체간의 통신을 Signal 이라는 기능으로 구현한다.
public class PlayerDamagedSignal : Signal<PlayerDamagedSignal, int>
{
}
public class Player
{
private int _health;
PlayerDamagedSignal _onPlayerDamaged;
public Player(int health, PlayerDamagedSignal onPlayerDamaged)
{
_health = health;
_onPlayerDamaged = onPlayerDamaged;
}
public void TakeDamage(int amount)
{
_health -= amount;
_onPlayerDamaged.Fire(amount);
}
}
public class GameInstaller : MonoInstaller
{
[SerializeField] private GameObject _damageTextPrefab;
Container.Bind<Player>().AsSingle().WithArguments(100);
Container.DeclareSignal<PlayerDamagedSignal>();
Container.BindSignal<int, PlayerDamagedSignal>()
.To<CombatTextFactory>((factory, damageAmount) =>
{
factory.Create($"-{damageAmount} HP");
}).AsSingle().WithArguments(_damageTextPrefab);
}