I have a Timer
class that implements the standard Zenject ITickable
interface:
Timer: ITickable {
public void Tick() {}
}
I want to create a new instance of Timer
for every class that asks for it.
I do this (I want bind ITickable
to Timer
):
Container.BindInterfacesAndSelfTo<Timer>().AsTransient();
I get dependency, but method Tick()
is not called.
And if I change the registration to AsSingle:
Container.BindInterfacesAndSelfTo<Timer>().AsSingle();
the method Tick()
is called normally.
How can I get a new instance of Timer
with ITickable
AsTransient()?
TickableManager
is a manager that is responsable for IxTickable interfaces.
It gets a list of instances by injection. So when Zenject binder injecting dependencies in classes, it looks for certain provider that implements method to get exact object. So when you use .AsTransient it calls transient provider. And its instruction is to return a new instance, when someone is asking for it. So as TickableManager._tickables
is a List<ITickables>
that injected as well, the instance created by transient provider for this list is also brand new.
So you have 3 options here:
Container.Bind<Timer>().AsTransient()
.OnInstantiated<Timer>((_context,_object)=>
_context.Container.Resolve<TickableManager>()
.Add(_object)
);
Container.Bind(typeof(ITickable),typeof(Timer)).WithId(1).To<Timer>().AsSingle();
Container.Bind(typeof(ITickable),typeof(Timer)).WithId(2).To<Timer>().AsSingle();
GameObjectContext
for each object. And if you are trying to create some sort of collection of game entities: enemies, weapons ,NPC, etc, this approach is the best. You just have to add GameObjectContext
to the root of an entity prefab. And then create installer for this context, where Timer should be binded .AsSingle.That was really tough question. It took several hours to find out the solution. I've already regretted taking on this question.
P.S. Don't be affraid to press F12 and Ctrl+F12 in your IDE to seek something in external libraries. You gain important experience by acting like this.