VContainer icon indicating copy to clipboard operation
VContainer copied to clipboard

Multiple instances of singleton?

Open Toernblom opened this issue 1 year ago • 4 comments

I've added a gameObject to the VContainerSettings and attached my rootLifetimeScope In that rootLifetimeScope:

builder.Register<GameManager>(Lifetime.Singleton);
builder.RegisterEntryPoint<GameManager>();

Then in one of my scenes I've got a "PlayableSceneScope" which I've put on a gameObject, changed parent to the rootLifetimeScope. In that PlayableSceneScope i do:

builder.Register<ServerConnectionController>(Lifetime.Singleton);
builder.RegisterEntryPoint<ServerConnectionController>();

In the ServerConnectionController

[Inject]
private readonly GameManager _gameManager;

In the GameManager, I've got a start method:

public void Start()
  {
      testInt = 15;
  }

If i print that value from inside GameManager its fine, if i try to access it from ServerConnectionController which was registered by the child of the rootLifeTimeScope that value is 0, not 15, why?

Toernblom avatar Sep 29 '24 09:09 Toernblom

image

image

The VContainer Diagnostics clearly shows its the same instance right?

Toernblom avatar Sep 29 '24 09:09 Toernblom

image

Are there different instances depending on the contract type?

Toernblom avatar Sep 29 '24 09:09 Toernblom

I fixed it by removing RegisterEntrypoint, adding a monobehaviour called "StartCaller" that calls Start instead. I dont think this is how its supposed to work..?

Toernblom avatar Sep 29 '24 09:09 Toernblom

I don't think you're supposed to use both Register and RegisterEntryPoint - if I understand correctly RegisterEntryPoint is just a convenience wrapper around Register that only handles entry point interface implementations (IStartable, IDisposable, etc.). You could try using builder.Register<T>.AsImplementedInterfaces().AsSelf() as that will register the type, bind it by its own type (T) and any interfaces it implements.

You can use Start inside the LifetimeScope (your root lifetime scope), as it's essentially just a MonoBehaviour underneath

RamiAhmed avatar Oct 03 '24 09:10 RamiAhmed

You asked it to register 2 instances, and you got two. That's how it's supposed to work because VContainer supports collections. Register entry point just registers with implemented interfaces:

public static RegistrationBuilder RegisterEntryPoint<T>(
            this IContainerBuilder builder,
            Lifetime lifetime = Lifetime.Singleton)
        {
            EntryPointsBuilder.EnsureDispatcherRegistered(builder);
            return builder.Register<T>(lifetime).AsImplementedInterfaces();
        }

lucasmontec avatar Oct 24 '24 16:10 lucasmontec

public class GameEntryPoint : IStartable
{
    private readonly GameManager _gameManager;

    public GameEntryPoint(GameManager gameManager)
    {
        _gameManager = gameManager;
    }

    public void Start()
    {
        _gameManager.Initialize(); // Sets testInt or other initial values here
    }
}

Try using a GameEntryPoint to initialize GameManager and register GameEntryPoint in the RootLifetimeScope.

builder.Register<GameManager>(Lifetime.Singleton);
builder.RegisterEntryPoint<GameEntryPoint>();

stenyin avatar Oct 27 '24 17:10 stenyin