在 ProjectContext 上使用 Zenject FromSubContainerResolve 到 SceneContext
Use Zenject FromSubContainerResolve on ProjectContext to SceneContext
我有一个 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
的子容器。所以我应该可以在 ProjectInstaller
中使用 FromSubContainerResolve
来绑定子场景中的项目,也许可以添加一行:
// ProjectInstaller.cs
public override void InstallBindings() {
// ...
Container.Bind<Modal>().To<InventoryManager>().FromSubContainerResolve();
}
但我不确定这 11 种 FromSubContainerResolve
方法中的哪一种对这种情况有意义。它们似乎都与具有游戏对象上下文的预制件相关,不 用于 ProjectContext
.
这个用例有意义吗?有没有更简单或更好的方法?
问题是 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>();
}
}
我有一个 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
的子容器。所以我应该可以在 ProjectInstaller
中使用 FromSubContainerResolve
来绑定子场景中的项目,也许可以添加一行:
// ProjectInstaller.cs
public override void InstallBindings() {
// ...
Container.Bind<Modal>().To<InventoryManager>().FromSubContainerResolve();
}
但我不确定这 11 种 FromSubContainerResolve
方法中的哪一种对这种情况有意义。它们似乎都与具有游戏对象上下文的预制件相关,不 用于 ProjectContext
.
这个用例有意义吗?有没有更简单或更好的方法?
问题是 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>();
}
}