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

如何基于运行时参数绑定Factory对象的派生类(Zenject)

可行方案实现运行时动态绑定角色派生类

你当前的核心问题是CharacterInstaller在初始化阶段就完成了依赖绑定,无法响应运行时传入的角色类型参数。下面提供几种针对Zenject+对象池场景的解决方案,核心思路是将依赖绑定时机推迟到角色实例创建的运行时刻:


方案一:角色内部根据类型动态初始化依赖

修改Character类,通过注入的容器实例,在对象从池取出时根据类型解析对应的攻击系统:

public enum 角色类型
{
    近战,
    远程,
}

public class Character : MonoBehaviour, IPoolable<IMemoryPool>
{
    private IAttackSystem _攻击系统;
    private DiContainer _容器;
    private 角色类型 _当前类型;
    private IMemoryPool _对象池;

    [Inject]
    public void 初始化容器(DiContainer container)
    {
        _容器 = container;
    }

    // 对象池取出时调用,传入运行时类型参数
    public void 生成初始化(角色类型 类型)
    {
        _当前类型 = 类型;
        创建对应攻击系统();
    }

    private void 创建对应攻击系统()
    {
        switch (_当前类型)
        {
            case 角色类型.近战:
                _攻击系统 = _容器.Instantiate<MeleeAttackSystem>();
                break;
            case 角色类型.远程:
                _攻击系统 = _容器.Instantiate<RangedAttackSystem>();
                break;
        }
    }

    public void 回收清理()
    {
        if (_攻击系统 is IDisposable 可释放资源)
        {
            可释放资源.Dispose();
        }
        _攻击系统 = null;
        _对象池.Despawn(this);
    }

    public void 设置对象池(IMemoryPool pool)
    {
        _对象池 = pool;
    }
}

// 自定义带类型参数的角色工厂
public class 角色工厂 : PlaceholderFactory<角色类型, Character>
{
}

public class 角色创建器
{
    private 角色工厂 _工厂;

    [Inject]
    public 角色创建器(角色工厂 factory)
    {
        _工厂 = factory;
    }

    public void 创建近战角色()
    {
        _工厂.Create(角色类型.近战);
    }

    public void 创建远程角色()
    {
        _工厂.Create(角色类型.远程);
    }
}

public class CharacterInstaller : MonoInstaller
{
    public GameObject 角色预制体;

    public override void InstallBindings()
    {
        // 绑定角色对象池
        Container.BindMemoryPool<Character, Character.Pool>()
            .WithInitialSize(5)
            .FromComponentInNewPrefab(角色预制体)
            .UnderTransformGroup("角色对象组");

        // 绑定自定义工厂
        Container.Bind<角色工厂>().AsSingle();

        // 提前注册攻击系统实现,方便动态解析
        Container.Bind<MeleeAttackSystem>().AsTransient();
        Container.Bind<RangedAttackSystem>().AsTransient();
    }
}

方案二:用子容器实现类型专属依赖绑定

为不同类型的角色预制体创建独立子容器,每个子容器绑定对应类型的依赖:

public enum 角色类型
{
    近战,
    远程,
}

public class CharacterInstaller : MonoInstaller
{
    public GameObject 近战角色预制体;
    public GameObject 远程角色预制体体;

    public override void InstallBindings()
    {
        // 为近战角色绑定子容器及专属依赖
        Container.BindSubContainerForPrefab<Character>(近战角色预制体)
            .ByInstalling<近战角色子容器安装器>();

        // 为远程角色绑定子容器及专属依赖
        Container.BindSubContainerForPrefab<Character>(远程角色预制体)
            .ByInstalling<远程角色子容器安装器>();

        // 绑定根据类型选择预制体的工厂
        Container.BindFactory<角色类型, Character, Character.Factory>()
            .FromFactory<按类型选预制体工厂>();
    }
}

// 自定义工厂:根据运行时类型选择对应预制体
public class 按类型选预制体工厂 : IFactory<角色类型, Character>
{
    private readonly DiContainer _容器;
    private readonly GameObject _近战预制体;
    private readonly GameObject _远程预制体;

    [Inject]
    public 按类型选预制体工厂(DiContainer container,
        [Inject(Id = "近战角色")] GameObject 近战预制体,
        [Inject(Id = "远程角色")] GameObject 远程预制体)
    {
        _容器 = container;
        _近战预制体 = 近战预制体;
        _远程预制体 = 远程预制体;
    }

    public Character Create(角色类型 类型)
    {
        var 目标预制体 = 类型 == 角色类型.近战 ? _近战预制体 : _远程预制体;
        return _容器.InstantiateComponent<Character>(目标预制体);
    }
}

// 近战角色专属依赖安装器
public class 近战角色子容器安装器 : MonoInstaller
{
    public override void InstallBindings()
    {
        Container.Bind<IAttackSystem>().To<MeleeAttackSystem>().AsSingle();
    }
}

// 远程角色专属依赖安装器
public class 远程角色子容器安装器 : MonoInstaller
{
    public override void InstallBindings()
    {
        Container.Bind<IAttackSystem>().To<RangedAttackSystem>().AsSingle();
    }
}

方案三:通过带参数工厂直接传入依赖

在创建角色时,先解析对应类型的攻击系统,再作为参数传入角色实例:

public class Character : MonoBehaviour, IPoolable<IMemoryPool>
{
    private IAttackSystem _攻击系统;
    private IMemoryPool _对象池;

    // 初始化时直接传入已解析的攻击系统
    public void 初始化(IAttackSystem 攻击系统)
    {
        _攻击系统 = 攻击系统;
    }

    public void 回收清理()
    {
        if (_攻击系统 is IDisposable 可释放资源)
        {
            可释放资源.Dispose();
        }
        _攻击系统 = null;
        _对象池.Despawn(this);
    }

    public void 设置对象池(IMemoryPool pool)
    {
        _对象池 = pool;
    }
}

// 带攻击系统参数的角色工厂
public class 角色工厂 : PlaceholderFactory<IAttackSystem, Character>
{
}

public class 角色创建器
{
    private 角色工厂 _工厂;
    private DiContainer _容器;

    [Inject]
    public 角色创建器(角色工厂 factory, DiContainer container)
    {
        _工厂 = factory;
        _容器 = container;
    }

    public void 创建近战角色()
    {
        var 近战攻击系统 = _容器.Instantiate<MeleeAttackSystem>();
        _工厂.Create(近战攻击系统);
    }

    public void 创建远程角色()
    {
        var 远程攻击系统 = _容器.Instantiate<RangedAttackSystem>();
        _工厂.Create(远程攻击系统);
    }
}

public class CharacterInstaller : MonoInstaller
{
    public GameObject 角色预制体;

    public override void InstallBindings()
    {
        Container.BindMemoryPool<Character, Character.Pool>()
            .WithInitialSize(5)
            .FromComponentInNewPrefab(角色预制体)
            .UnderTransformGroup("角色对象组");

        Container.Bind<角色工厂>().AsSingle();
        Container.Bind<MeleeAttackSystem>().AsTransient();
        Container.Bind<RangedAttackSystem>().AsTransient();
    }
}

内容的提问来源于stack exchange,提问作者Enescan BEKTAŞ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:46:06