You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Zenject的Project Context工厂中解析Scene Context依赖?

解决Zenject跨容器依赖解析问题

问题原因很明确:StateFactory是在**ProjectContext(全局容器)中绑定的,它默认使用全局容器来解析依赖;而IFruitSpawner是在SceneContext(场景容器)**中绑定的,全局容器无法访问场景容器内的绑定项,所以创建GameplayState时找不到IFruitSpawner的实现。

下面是三种可行的解决方案,根据你的业务场景选择:

方案1:手动传递SceneContext容器给StateFactory

这种方式可控性最强,适合StateMachine必须放在全局的场景。

步骤:

  1. 修改StateFactory,添加接收场景容器的方法/属性:
public class StateFactory
{
    private readonly DiContainer _globalContainer;
    private DiContainer _currentSceneContainer;

    // 注入全局容器
    public StateFactory(DiContainer globalContainer)
    {
        _globalContainer = globalContainer;
    }

    // 供SceneContext调用,设置当前场景的容器
    public void SetCurrentSceneContainer(DiContainer sceneContainer)
    {
        _currentSceneContainer = sceneContainer;
    }

    public TState CreateState<TState>() where TState : StateBase
    {
        // 优先用场景容器解析,没有则回退到全局容器
        return _currentSceneContainer != null && _currentSceneContainer.HasBinding<TState>()
            ? _currentSceneContainer.Instantiate<TState>()
            : _globalContainer.Instantiate<TState>();
    }
}
  1. 在SceneContext的Installer中,把当前容器传递给全局的StateFactory:
public class FruitsInstaller : Installer<FruitsInstaller>
{
    public override void InstallBindings()
    {
        Container.Bind<IFruitSpawner>().To<FruitSpawner>().AsSingle();

        // 从全局容器获取StateFactory,传入当前场景容器
        var stateFactory = Container.Resolve<StateFactory>();
        stateFactory.SetCurrentSceneContainer(Container);
    }
}

方案2:通过Zenject API获取当前活跃的SceneContext容器

利用Zenject内置的上下文查找机制,自动获取当前场景的容器,代码更简洁。

修改StateFactory的CreateState方法:

public class StateFactory
{
    private readonly DiContainer _globalContainer;

    public StateFactory(DiContainer globalContainer)
    {
        _globalContainer = globalContainer;
    }

    public TState CreateState<TState>() where TState : StateBase
    {
        // 获取当前场景的SceneContext(确保场景已加载完成)
        var currentSceneCtx = SceneContext.CurrentSceneContext;
        
        if (currentSceneCtx != null && currentSceneCtx.Container.HasBinding<IFruitSpawner>())
        {
            return currentSceneCtx.Container.Instantiate<TState>();
        }

        return _globalContainer.Instantiate<TState>();
    }
}

注意:SceneContext.CurrentSceneContext仅在场景加载完成后有效,要确保调用CreateState时目标场景已经初始化完毕。

方案3:将StateMachine相关绑定移到SceneContext

如果你的StateMachine和GameplayState是和当前场景强绑定的(比如每个场景有独立的状态逻辑),直接把StateMachineInstaller移到SceneContext中,让所有依赖处于同一个容器内,从根源避免跨容器问题。

操作:

  • 从ProjectContext的Installers列表中移除StateMachineInstaller
  • 将StateMachineInstaller添加到SceneContext的Installers列表中

这样StateFactory和IFruitSpawner都在同一个场景容器里,创建GameplayState时就能直接解析到依赖。


内容的提问来源于stack exchange,提问作者dest1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:12:57