2

我有一个 Unity + Zenject 设置,其中ProjectInstaller包含一些遵循“模态”界面的全局依赖项,例如,

public class ProjectInstaller : MonoInstaller {
  public override void InstallBindings() {
    Container.Bind<ModalManager>().AsSingle();

    Container.Bind<Modal>().To<DialogManager>().AsSingle();
  }
}

有些模态只与某些场景相关,所以我将它们绑定在SceneInstaller

public class SceneInstaller : MonoInstaller {
  public override void InstallBindings() {
    Container.BindInterfacesAndSelfTo<InventoryManager>()
      .FromComponentInNewPrefab(InventoryPrefab)
      .AsSingle()
  }
}

我想管理在项目范围内定义的单一的所有模式。ModalManager所以它有一个List<Modal>绑定:

public class ModalManager : MonoBehaviour {
    [Inject]
    protected List<Modal> _modals;
}

当我运行它时,ModalManager只有一个模式:在项目范围内定义的模式。据我了解,SceneContext它是ProjectContext. 所以我应该能够在子场景中使用FromSubContainerResolve绑定ProjectInstaller项目,也许通过添加如下行:

// ProjectInstaller.cs
public override void InstallBindings() {
  // ...
  Container.Bind<Modal>().To<InventoryManager>().FromSubContainerResolve();
}

但我不确定这 11FromSubContainerResolve种方法中的哪一种对这种情况有意义。它们似乎都与具有游戏对象上下文的预制件相关,而不是ProjectContext.

这个用例有意义吗?有没有更简单或更好的方法?

4

1 回答 1

2

问题是ModalManager只能注入直接添加到 ProjectContext 的依赖项。对于这类问题,我建议使用以下模式:

public interface IModal
{
}

public class ModalManager
{
    private readonly List<IModal> _modals = new List<IModal>();

    public IReadOnlyList<IModal> Modals
    {
        get { return _modals; }
    }

    public void AddModal(IModal modal)
    {
        _modals.Add(modal);
    }

    public bool RemoveModal(IModal modal)
    {
        return _modals.Remove(modal);
    }
}

public class ModalRegisterHandler : IInitializable, IDisposable
{
    private readonly List<IModal> _modals;
    private readonly ModalManager _modalManager;

    public ModalRegisterHandler(
        // We need to use InjectSources.Local here, otherwise we will
        // add any project context modals again in each scene
        [Inject(Source = InjectSources.Local)]
        List<IModal> modals, ModalManager modalManager)
    {
        _modals = modals;
        _modalManager = modalManager;
    }

    public void Initialize()
    {
        foreach (var modal in _modals)
        {
            _modalManager.AddModal(modal);
        }
    }

    public void Dispose()
    {
        // We don't want ModalManager to retain references to Modals defined in unloaded scenes
        // (dispose is executed on scene unload)
        foreach (var modal in _modals)
        {
            _modalManager.RemoveModal(modal);
        }
    }
}

public class SceneInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container.Bind<IModal>().To<FooModal>();
        Container.Bind<IModal>().To<BarModal>();
    }
}

public class ProjectInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        // We use CopyIntoDirectSubContainers so that ModalRegisterHandler gets automatically added to every 
        // scene context
        Container.BindInterfacesTo<ModalRegisterHandler>().AsSingle().CopyIntoDirectSubContainers();

        Container.Bind<ModalManager>().AsSingle();

        Container.Bind<IModal>().To<QuxModal>();
        Container.Bind<IModal>().To<FizzModal>();
    }
}
于 2022-02-04T17:35:50.230 回答