1

I am using Zenject for dependency injection in my game, and I am in an impasse.

Let me describe my current setup:

I have several characters with their own GameObjectContext and CharacterInstaller responsible for injecting a CharacterController into a CharacterPresenter.

public class CharacterInstaller : MonoInstaller<CharacterInstaller>
{
    public override void InstallBindings()
    {
        Container.BindInterfacesAndSelfTo<CharacterInstaller>().AsSingle().NonLazy();
    }
}
// PLAIN C# class
public class CharacterController : <some_interfaces>
{
    public void Foo()
    {
        // ...
    }
}
public class CharacterPresenter : MonoBehaviour
{
    private CharacterController characterController;

    [Inject]
    public void InjectDependencies( CharacterController characterController )
    {
        this.characterController = characterController;
    }

    public void Foo() => characterController.Foo();
}

What I would like to do is to also inject all the instances of the CharacterController class into a "Manager" class using List Bindings. This manager is not a parent of my characters, and I may need several managers.

public class CharactersManager
{
    private List<Character> characters;

    public CharactersManager( List<Character> characters)
    {
        this.characters = characters;
    }

    public void MakeCharactersDoSomething()
    {
        foreach ( Character character in characters)
            character.Foo();
    }
}

The closer things I found to solve my problem were:

• Attach a ZenjectBinding component to my Character and specify the context I need.
→ Can't work because CharacterController is a plain C# class and the ZenjectBinding only binds components

• Declare a Context in the CharacterInstaller and call OtherContext.Container.Bind...
→ Fails because OtherContext.Container is null

• Call Container.Bind<CharacterController>().FromComponentsInHierarchy() in my manager installer
→ Does not work because CharacterController is not a component

• Using a factory
→ I can't use it since my objects are meant to be placed at edit time in the editor

• Using Container.ParentContainers in my CharacterInstaller
→ Can't use it because my manager is not a parent container of my CharacterInstaller.Container

I am open to suggestions, maybe a refactoring of my setup if needed. Thanks in advance

Hellium
  • 7,206
  • 2
  • 19
  • 49

1 Answers1

1

Well, I found a solution, but it does not feel very great.

In an installer attached to the scene context, bind a List<CharacterController>

public class GameInstaller : MonoInstaller<GameInstaller>
{
    public override void InstallBindings()
    {
        Container.Bind<List<CharacterController>>().AsSingle();
    }
}

And in the CharacterInstaller, add the instantiated character to the injected list

public class CharacterInstaller : MonoInstaller<CharacterInstaller>
{
    private List<CharacterController> characters;

    [Inject]
    public void InjectDependencies( List<CharacterController> characters )
    {
        this.characters = characters;
    }

    public override void InstallBindings()
    {
        Container.BindInterfacesAndSelfTo<CharacterInstaller>()
            .AsSingle()
            .OnInstantiated<CharacterController>( ( context, character ) => characters.Add( character ) )
            .NonLazy();
    }
}
Hellium
  • 7,206
  • 2
  • 19
  • 49