Resolve from childs. #456
Replies: 1 comment
-
In general it goes against the idea of DI to resolve from child scopes. If an object has a dependency, then by definition that dependency is in the object's scope. Just like it's impossible to reference variables not in a classes scope, it's impossible for objects to reference dependencies not with their scope. However I understand what you're trying to achieve. I'll use an example I'm working on. I have a GameScope and a PlayerScope. The PlayerScope is a child to the GameScope. The PlayerScope registers a PlayerPosition. I want my Camera to reference the player's position. So I want to 'Resolve from Child' by getting the PlayerPosition from the PlayerScope, and making it available to the GameScope, such that the camera can access it. 1. Push the dependency into the parent scope.This is the simplest, and doesn't violate any DI principles. Register the PlayerPosition in the GameScope and remove the original registration from the PlayerScope so it doesn't get overwritten. Now everything that needs the PlayerPosition has it. However, that answer is not satisfying, because now your PlayerScope is dependent on the GameScope, which feels gross. I got around this by checking if the PlayerPosition had already been registered. public class PlayerScope : LifetimeScope
{
// A child can resolve from a parent, but a parent cannot resolve from a child.
protected override void Configure(IContainerBuilder builder)
{
if (Parent.container.Resolve<PlayerPosition>() is not null)
builder.Register<PlayerPosition>();
}
} The default behaviour is to resolve dependencies from the closest scope. However this pattern flips that around, and instead will resolve dependencies from the highest scope that registers the dependency. 2. Push the dependent into the child scopeAgain, if an object (the dependent) requires a dependency, they belong in the same scope. So you could always register the Camera inside the PlayerScope. However this is ugly, and is essentially the same as pushing the PlayerPosition into the parent scope. 3. Use a Factory.Technically it should be possible to return a child container from a factory. public class GameScope : LifetimeScope
{
[SerializedField] private PlayerScope playerScope;
protected override void Configure(IContainerBuilder builder)
{
builder.RegisterFactory<PlayerScope>(() => playerScope);
}
}
public class CameraController : MonoBehaviour
{
[Inject] private Func<PlayerScope> playerScopeFactory;
public void GetPlayerPosition()
{
var playerPosition = playerScopeFactory().Resolve<PlayerPosition>();
}
} However, injecting scopes is discouraged in IoC. |
Beta Was this translation helpful? Give feedback.
-
Assume I have MainGameLoop scope.
In this scope I want to register GameLoop class as entry point. GameLoop class loads main menu.
I want to GameLoop to subscribe on some event that will be fired in main menu. To do so I need to resolve some dependencies from child scope.
Is it possible to do so?
Beta Was this translation helpful? Give feedback.
All reactions