如何在Zenject中为BaseUnit传递自身引用至状态工厂?
如何在Zenject状态工厂中注入BaseUnit自身引用
嘿,这个问题我之前用Zenject做状态机架构的时候也碰到过!核心要解决的是让每个BaseUnit实例的专属UnitStateFactory能拿到自己的宿主引用,下面给你几个贴合Zenject最佳实践的解决方案:
方案1:用实例绑定+子容器(适合MonoBehaviour场景)
因为BaseUnit是MonoBehaviour,每个实例都是独立的,我们可以给每个BaseUnit创建一个专属的子容器,把自身实例绑定进去,再注入UnitStateFactory:
首先,确保你的UnitStateFactory构造函数已经接收BaseUnit参数:
public class UnitStateFactory { private readonly UnitMoveState.Factory _moveStateFactory; private readonly UnitActiveState.Factory _activeStateFactory; private readonly BaseUnit _owningUnit; public UnitStateFactory( UnitMoveState.Factory moveStateFactory, UnitActiveState.Factory activeStateFactory, BaseUnit owningUnit) { _moveStateFactory = moveStateFactory; _activeStateFactory = activeStateFactory; _owningUnit = owningUnit; } // 状态创建方法,比如生成移动状态 public IUnitState CreateMoveState() { return _moveStateFactory.Create(); } }
然后在BaseUnit的Awake方法里手动初始化子容器并注入:
public class BaseUnit : MonoBehaviour { [Inject] public UnitStateFactory StateFactory { get; private set; } private void Awake() { // 为当前Unit实例创建专属子容器 var subContainer = new DiContainer(); // 把自身实例绑定到容器中,确保Factory能拿到 subContainer.BindInstance(this).AsSingle(); // 绑定各个状态的工厂和总状态工厂 subContainer.Bind<UnitMoveState.Factory>().AsSingle(); subContainer.Bind<UnitActiveState.Factory>().AsSingle(); subContainer.Bind<UnitStateFactory>().AsSingle(); // 注入当前Unit的依赖(包括StateFactory) subContainer.Inject(this); } }
方案2:带参数的状态工厂(更灵活,避免循环依赖)
如果不想用子容器,也可以让状态的Factory接受BaseUnit作为创建参数,这样UnitStateFactory只需要持有自身的Unit引用,创建状态时传递进去:
首先修改状态类的Factory为带参数的版本:
public class UnitMoveState : IUnitState { private readonly BaseUnit _unit; // 构造函数接收BaseUnit public UnitMoveState(BaseUnit unit) { _unit = unit; } // 定义带参数的Zenject工厂 public class Factory : PlaceholderFactory<BaseUnit, UnitMoveState> { } }
然后在UnitStateFactory里创建状态时传入自身持有的Unit:
public IUnitState CreateMoveState() { // 把当前Factory持有的Unit传给状态工厂 return _moveStateFactory.Create(_owningUnit); }
这种方式不需要处理容器的上下文绑定,更适合状态需要动态切换宿主的场景。
方案3:用MonoInstaller做上下文绑定(最规范的Zenject方式)
如果你的项目已经在用Zenject的场景安装器,可以给BaseUnit配一个专属的MonoInstaller,把自身实例绑定到容器中:
先创建安装器类:
public class BaseUnitInstaller : MonoInstaller<BaseUnitInstaller> { // 在Inspector中把当前BaseUnit拖进来 public BaseUnit TargetUnit; public override void InstallBindings() { // 绑定当前Unit实例为单例 Container.BindInstance(TargetUnit).AsSingle(); // 绑定状态工厂和总工厂 Container.Bind<UnitMoveState.Factory>().AsSingle(); Container.Bind<UnitActiveState.Factory>().AsSingle(); Container.Bind<UnitStateFactory>().AsSingle(); } }
然后在BaseUnit的GameObject上挂载这个BaseUnitInstaller,并把TargetUnit字段设置为自身,这样Zenject在加载场景时会自动完成绑定,把正确的BaseUnit实例注入到UnitStateFactory中。
注意事项
- 如果出现循环依赖(
BaseUnit依赖UnitStateFactory,同时UnitStateFactory依赖BaseUnit),Zenject的单例绑定会自动处理这种情况,不用额外配置。 - 确保所有状态类的构造函数都正确接收
BaseUnit参数,Zenject会自动完成注入(如果用方案1或3),或者通过工厂参数传递(方案2)。
内容的提问来源于stack exchange,提问作者Argus Kos
相关产品推荐
相关产品推荐

