hadashiA / VContainer

The extra fast, minimum code size, GC-free DI (Dependency Injection) library running on Unity Game Engine.
https://vcontainer.hadashikick.jp
MIT License
1.88k stars 163 forks source link

Singletons: ensure there is no duplicate Singletons of the same type when bind/resolve them in child-scope! #618

Open Watcher3056 opened 7 months ago

Watcher3056 commented 7 months ago

Hi! I have a bit specific case(or not). In my game I have:

What I want is to declare all needed dependencies only for specific scene. For example for specific Level. While so there should be possibility to declare similar dependencies(I mean bind same Singletons) in other scenes.

What I want to achieve:

In my current situation when entering Entry Point Scope(Entry Scene) and it loads Level(Level Scope) 3 instances of the same Singleton creating despite the fact it's already declared(bind) in a Root Scope.

image

RootScope:

public class RootScope : LifetimeScope
{
    [SerializeField]
    private CameraManager cameraManagerPrefab;

    protected override void Configure(IContainerBuilder builder)
    {
        base.Configure(builder);

        builder.RegisterComponentInNewPrefab<CameraManager>(cameraManagerPrefab, Lifetime.Singleton);
    }
    private void Start()
    {
        DontDestroyOnLoad(Container.Resolve<CameraManager>());
    }
}

Entry Point Scope:

public class EntryPointScope : LifetimeScope
{
    [SerializeField]
    private CameraManager cameraManagerPrefab;

    protected override void Configure(IContainerBuilder builder)
    {
        base.Configure(builder);

        builder.RegisterComponentInNewPrefab<CameraManager>(cameraManagerPrefab, Lifetime.Singleton);
    }
    private void Start()
    {
        DontDestroyOnLoad(Container.Resolve<CameraManager>());

        SceneManager.LoadScene(gameObject.scene.buildIndex + 1, LoadSceneMode.Additive);
    }
}

Level Scope:

public class LevelScope : LifetimeScope
{
    [SerializeField]
    private CameraManager cameraManagerPrefab;

    protected override void Configure(IContainerBuilder builder)
    {
        base.Configure(builder);

        builder.RegisterComponentInNewPrefab<CameraManager>(cameraManagerPrefab, Lifetime.Singleton);
    }
    private void Start()
    {
        DontDestroyOnLoad(Container.Resolve<CameraManager>());
    }
}

Note: only two instances of CameraManager was actually created(one from Entry Point Scope and another from Level Scope), because Root Scope Start() was not triggered, so it wasn't resolved and created. Also seems like there is no possibilities to trigger non-lazy Singleton creation from the Root Scope to ensure CameraManager is instantiated(else your would not be able to see the game, lol)