Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MemoryPool<Param, Value> with CustomFactory #286

Open
vodoleystudio opened this issue Apr 30, 2023 · 1 comment
Open

MemoryPool<Param, Value> with CustomFactory #286

vodoleystudio opened this issue Apr 30, 2023 · 1 comment

Comments

@vodoleystudio
Copy link

Describe the bug
I try to create a pool that gets param and value because I need this param in my custom factory for the correct initializing of instantiated objects.

The version without the param works as expected - (I mean MemoryPool, and related to it factories)

Unfortunately, the version with param cause to the exception that not clear to me why it's trying to resolve IFactory instead of the requested one - IFactory<IAtata, IKokoko>

When :
Container.Instantiate<MemoryPool<IAtata, IKokoko>>(new object[] { settings, factory });
the line is running, I get an error :
ZenjectException: Unable to resolve 'IFactory' while building object with type 'MemoryPool<IAtata, IKokoko>'. Object graph: MemoryPool<IAtata, IKokoko>

To Reproduce
Run an attached code in editor.

Expected behavior
That it will inject all as expected.

Screenshots
image

Extenject and Unity info (please complete the following information):

  • Zenject version: 9.2.0
  • Unity version: 2022.2.14
  • Project's scripting backend [e.g. Mono/IL2CPP] : IL2CPP

Additional context

public interface IAtata
{
    string Name { get; set; }
}

public interface IKokoko
{
    string Name { get; set; }
}

public class Kokoko : IKokoko
{
    public string Name { get; set; }

    public class Factory : PlaceholderFactory<IAtata, IKokoko>
    {
    }
}

public class KokokoFactory : IFactory<IAtata, IKokoko>
{
    public IKokoko Create(IAtata atata)
    {
        IKokoko kokoko = new Kokoko();
        kokoko.Name = atata.Name;
        return kokoko;
    }
}

public class Installer : MonoInstaller<Installer>
{
    public override void InstallBindings()
    {
        var settings = new MemoryPoolSettings()
        {
            InitialSize = 100,
            ExpandMethod = PoolExpandMethods.Double,
        };

        Container.BindFactory<IAtata, IKokoko, Kokoko.Factory>().FromFactory<KokokoFactory>().NonLazy();

        var factory = Container.Resolve<Kokoko.Factory>();

        // ZenjectException: Unable to resolve 'IFactory<IKokoko>' while building object with type 'MemoryPool<IAtata, IKokoko>'. Object graph: MemoryPool<IAtata, IKokoko>
        var pool = Container.Instantiate<MemoryPool<IAtata, IKokoko>>(new object[] { settings, factory });
    }
}
@Extrys
Copy link

Extrys commented Jan 24, 2024

In order to instantiate the pool correctly you should more likelly create a factory of pools, so you prepare that factory with the needed settings for the pool to be created as you like

also you wouldnt need to resolve in the install phase

your code should look like this with these changes

public interface IAtata
{
	string Name { get; set; }
}

public interface IKokoko
{
	string Name { get; set; }
}

public class Kokoko : IKokoko
{
	public string Name { get; set; }

	public class Pool : MemoryPool<IAtata>
	{
		public class Factory : PlaceholderFactory<IAtata, Pool> { }
		public class Settings : MemoryPoolSettings { }
	}
}

public class Installer : MonoInstaller<Installer>
{
	public override void InstallBindings()
	{
                var settings = new  Kokoko.Pool.Settings ()
                {
                    InitialSize = 100,
                    ExpandMethod = PoolExpandMethods.Double,
                };
		Container.BindInstance(settings ).AsSingle();
		Container.BindFactory<IAtata, Kokoko.Pool, Kokoko.Pool.Factory>().FromFactory<CustomPoolFactory>();
	}
}

public class CustomPoolFactory : IFactory<IAtata, Kokoko.Pool>
{
	readonly DiContainer container;
	readonly Kokoko.Pool.Settings settings;

	public CustomMyIKokoPoolFactory(DiContainer container, Kokoko.Pool.Settings settings)
	{
		this.container = container;
		this.settings = settings;
	}

	public Kokoko.Pool Create(IAtata atata)
	{
		var extraArgs = new object[] { settings, new KokokoFactory(atata) };
		return container.Instantiate<Kokoko.Pool>(extraArgs);
	}
}


public class KokokoFactory : IFactory<IKokoko>
{
	IAtata atata;
	public KokokoFactory(IAtata atata) => this.atata = atata;

	public IKokoko Create()
	{
		IKokoko kokoko = new Kokoko();
		kokoko.Name = atata.Name;
		return kokoko;
	}
}

Also as an extra note, technically you should never resolve in the install phase as some injects are queued, and the install phase may have not finished yet on other installers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants