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

Circular Dependency with GameObjectContext #6

Closed
Maesla opened this issue Apr 26, 2019 · 2 comments
Closed

Circular Dependency with GameObjectContext #6

Maesla opened this issue Apr 26, 2019 · 2 comments

Comments

@Maesla
Copy link

Maesla commented Apr 26, 2019

Hello.

There is a problem with circular dependencies between a Subcontainer in a GameObjectContext and a type in the scene context
Main -> Foo (Main in GameObjectContext)
Foo-> Main (Foo in SceneContext)
In older versions, this caused that the GameObjectContext to be instantiated several times.

I have seen that now this is prevented by SubContainerCreatorCached._isLookingUp.

But I think the real issue is here:

public DiContainer CreateSubContainer(List<TypeValuePair> args, InjectContext context)
{
		if (_subContainer == null) // <======HERE
		{
			Assert.That(!_isLookingUp,
				"Found unresolvable circular dependency when looking up sub container!  Object graph:\n {0}", context.GetObjectGraphString());
			_isLookingUp = true;

			 // <===== AND HERE===========>
			_subContainer = _subCreator.CreateSubContainer(new List<TypeValuePair>(), context);

			_isLookingUp = false;

			Assert.IsNotNull(_subContainer);
		}

		return _subContainer;
}

_subCreator.CreateSubContainer has two parts, the creation and the injection, but the _subContainer reference is got after the injection, so

  1. Resolve Main. We are in CreateSubContainer.
  2. Instantiate GameobjectContext
  3. To Resolve Main, we have to resolve Foo
  4. To Resolve Foo, we have to resolve Main (circular dependency)
  5. Resolve Main. We are in CreateSubContainer again
  6. Because we still are inside the flow of the first resolve main, CreateSubContainer hasn't finish and _ subContainer is still null
  7. if (_subContainer == null) returns true
  8. In older versions, other GameobjectContext is instantiated twice. In the new versions, a exception is throw.

I think a solution to this could be to split CreateSubContainer in two parts.
The first part would be to instantiate the gameobject context, create a subcontainer, set it to the gameobject context and get the reference in SubContainerCreatorCached.
After this, we inject the gameobject context. This way, if we enter again in CreateSubContainer because of a circular dependency, _subContainer is no longer null
I have done a very dirty prototype just to illustrate what I mean.
What do you think?

Thank you

public DiContainer CreateSubContainer(List<TypeValuePair> args, InjectContext context)
{
		if (_subContainer == null)
		{
			SubContainerCreatorByNewPrefab creatorByPrefab = (SubContainerCreatorByNewPrefab)_subCreator;
			DiContainer sub = null;
			GameObjectContext goContext = null;
			creatorByPrefab.CreateRawSubContainer(new List<TypeValuePair>(), out sub, out goContext);
			_subContainer = sub;
			creatorByPrefab.InjectSubcontainer(goContext);

			Assert.IsNotNull(_subContainer);
		}

		return _subContainer;
	}
}
        public void CreateRawSubContainer(List<TypeValuePair> args, out DiContainer subcontainer, out GameObjectContext context)
        {
            Assert.That(args.IsEmpty());
            Object prefab = _prefabProvider.GetPrefab();

            bool shouldMakeActive;
            GameObject instance = _container.CreateAndParentPrefab(prefab, _gameObjectBindInfo, null, out shouldMakeActive);
            instance.SetActive(shouldMakeActive);
            context = instance.GetComponent<GameObjectContext>();
            context.SetContainerForCircularDependencyWorkarround(_container.CreateSubContainer());
            subcontainer = context.Container;

        }

        public void InjectSubcontainer(GameObjectContext context)
        {
            _container.InjectGameObject(context.gameObject);
        }
@svermeulen
Copy link

Yeah that makes sense to me. Triggering injection of the game object context after storing the _subcontainer reference would help solve this problem. This same pattern is used in other provider classes (like CachedProvider) specifically to allow for circular dependencies. So we should do the same in this case as well

svermeulen added a commit that referenced this issue May 3, 2019
…at are used with FromSubContainerResolve factory (issue #6)
@svermeulen
Copy link

svermeulen commented May 5, 2019

Ok this should be fixed now. This change should address a lot of other existing problems with circular dependencies + FromSubContainerResolve too. Thanks for reporting this

starikcetin referenced this issue in starikcetin/Extenject Aug 14, 2019
…at are used with FromSubContainerResolve factory (issue #6)
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