Closed sebastianfeistl closed 1 year ago
@sebastianfeistl You must specify contract IStartable when describing descriptor.AddTransient(typeof(Dot), typeof(IStartable));
like you did with your singleton.
Let me know if it worked
@gustavopsantos Thanks for the quick response. I already tried that but that throws the following error when running play mode:
public class DotInstaller : MonoBehaviour, IInstaller
{
public void InstallBindings(ContainerDescriptor descriptor)
{
descriptor.AddTransient(typeof(Dot), typeof(IStartable));
descriptor.AddSingleton(typeof(DotManager), typeof(IStartable));
}
}
UnknownContractException: Cannot resolve contract 'Dot'.
Reflex.Core.Container.GetResolvers (System.Type contract) (at ./Library/PackageCache/com.gustavopsantos.reflex@61f65bf967/Core/Container.cs:119)
Reflex.Core.Container.Resolve (System.Type type) (at ./Library/PackageCache/com.gustavopsantos.reflex@61f65bf967/Core/Container.cs:80)
Reflex.Core.Container.Resolve[TContract] () (at ./Library/PackageCache/com.gustavopsantos.reflex@61f65bf967/Core/Container.cs:85)
DotManager.CreateDot () (at Assets/Scripts/Gameplay/Dots/DotManager.cs:27)
DotManager.Start () (at Assets/Scripts/Gameplay/Dots/DotManager.cs:19)
Reflex.Core.ContainerDescriptor.Build () (at ./Library/PackageCache/com.gustavopsantos.reflex@61f65bf967/Core/ContainerDescriptor.cs:38)
Reflex.Core.Container.Scope (System.String name, System.Action`1[T] extend) (at ./Library/PackageCache/com.gustavopsantos.reflex@61f65bf967/Core/Container.cs:58)
Reflex.Injectors.UnityInjector.CreateSceneContainer (UnityEngine.SceneManagement.Scene scene, Reflex.Core.Container projectContainer) (at ./Library/PackageCache/com.gustavopsantos.reflex@61f65bf967/Injectors/UnityInjector.cs:85)
Reflex.Injectors.UnityInjector+<>c__DisplayClass3_0.<BeforeAwakeOfFirstSceneOnly>g__InjectScene|0 (UnityEngine.SceneManagement.Scene scene, UnityEngine.SceneManagement.LoadSceneMode mode) (at ./Library/PackageCache/com.gustavopsantos.reflex@61f65bf967/Injectors/UnityInjector.cs:32)
UnityEngine.SceneManagement.SceneManager.Internal_SceneLoaded (UnityEngine.SceneManagement.Scene scene, UnityEngine.SceneManagement.LoadSceneMode mode) (at <3b24cc7fa9794ed8ab04312c53e6dedd>:0)
Ohh sorry, you are right. In order for Dot to be resolved with contract Dot, you need to define this contract too, as the following:
descriptor.AddTransient(typeof(Dot), contracts: new[] { typeof(Dot), typeof(IStartable) });
With this definition what will happen is:
1- When the container is built, all IStartables will be constructed, and then, Start'ed, this will force one instance of Dot to be constructed, but as this dependency is Transient, next resolve will create a new instance.
2- Second time you are going to resolve for Dot, only constructor will be called, since IStartable::Start are only invoked when container get built, a new instance will be provided here, since you defined it as transient.
IStartable are mostly used to force a Singleton that is lazy by default, to be non lazy, so it gets constructed just after the container is built, rather than on first time is requested.
What exactly do you need? If you give me more in-depth information I may be able to indicate a better solution.
Thanks for the explanation. I ended up removing the IStartable
interface from the Dot class and made a dedicated initialization method:
public class DotManager : IStartable
{
public DotManager(Container container)
{
_container = container;
}
public void Start()
{
CreateDot();
}
// Factory method that creates a new instance and initializes the object
private Dot CreateDot()
{
var dot = _container.Resolve<Dot>();
dot.Initialize();
return dot;
}
}
public class Dot
{
public void Initialize()
{
// Called manually by factory method
}
}
I was thinking of IStartable
as some kind of initialization method that is called on automatically when the Transient is resolved but I assume that the example I provided above is an acceptable solution.
Thanks for the support and keep up the good work!
I'm seeking clarification and an example regarding the behavior of
IStartable
components when registered as Transients in the Reflex framework. The documentation mentions that "IStartable also works for Transients", but I can't figure out how to ensure that theStart
method is automatically called upon resolution when using Transients.Could you please provide an example or further guidance on registering and resolving
IStartable
components as Transients while ensuring that theStart
method is automatically invoked?Any assistance or insights on this topic would be highly appreciated.
Here's my setup: