ssannandeji / Zenject-2019

Dependency Injection Framework for Unity3D
MIT License
2.53k stars 366 forks source link

WhenInjected Into lead to crash under specific circumstances #650

Open FriedrichWessel opened 4 years ago

FriedrichWessel commented 4 years ago

Hello,

I have a special case : I would like to have a class fully Injected when injected into a service, but just the interfaces in the rest of the world. Basicly like this:

var secretInstance = Container.Instantiate<PrivateModel>(); Container.BindInterfacesTo<PrivateModel>().FromInstance(secretInstance); Container.Bind<PrivateModel>().FromInstance(secretInstance).WhenInjectedInto<SecretService>();

But I would like to get rid of the instance creation inside the ctor.

So I tried: Container.BindInterfacesTo().AsSingle(); Container.Bind().FromResolve().WhenInjectedInto();

But the second line causes a unity editor crash.

Beside that the crash should not happen - any suggestion how to achieve that ?

Thanks for your help !

Full testcode for reference:

using UnityEngine;
using Zenject;

public class FromResolveInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container.Bind<IInitializable>().To<World>().AsSingle();

        var secretInstance = Container.Instantiate<PrivateModel>();
        Container.BindInterfacesTo<PrivateModel>().FromInstance(secretInstance);
        Container.Bind<PrivateModel>().FromInstance(secretInstance).WhenInjectedInto<SecretService>();
        // this line crashes unity
        //Container.Bind<PrivateModel>().FromResolve().WhenInjectedInto<SecretService>();
        // This cannot resolve the interface afterwards 
        //Container.Bind<PrivateModel>().AsSingle().WhenInjectedInto<SecretService>();
        //Container.Bind<PublicInterfaceToModel>().To<PrivateModel>().FromResolve();

        Container.Bind<SecretService>().AsSingle();
        Container.Bind<SomeDude>().AsSingle();
        Container.Bind<SneakyDude>().AsSingle();
    }
}

public interface PublicInterfaceToModel
{
    void Open();
}

public class World : IInitializable
{

    public World(SecretService secretService, SomeDude dude, SneakyDude sneakyDude)
    {
    }

    public void Initialize()
    {
    }
}

public class PrivateModel : PublicInterfaceToModel
{
    public void Secret()
    {
        Debug.Log("Do Secret stuff");
    }

    public void Open()
    {
        Debug.Log("Do Private stuff");
    }
}

public class SecretService
{
    public SecretService(PrivateModel model)
    {
        model.Secret();
    }
}

public class SneakyDude
{
    // This should throw an Inject error
    /*public SneakyDude(PrivateModel nope)
    {
        nope.Secret();
    }*/
}

public class SomeDude
{
    public SomeDude(PublicInterfaceToModel model)
    {
        model.Open();
    }
}