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

如何实现字符串默认采用继承链类名拼接格式存储预制件路径?

实现继承链式预制件路径的几种方案

针对你的类继承结构,要生成基类类名/子类类名/.../prefabID格式的itemPath,我整理了几个实用的实现思路和替代方案,帮你搞定这个需求:

方案1:利用反射自动生成继承链路径(推荐,低维护成本)

这个方案的核心是通过反射获取当前类的完整继承层次,自动拼接出路径前缀,完全不用手动维护每个子类的路径。修改你的Item基类如下:

public class Item 
{ 
    public string itemPath; 
    public string prefabID; 

    protected virtual void Initialize() 
    { 
        // 收集从当前类向上到Item的所有类型
        var typeHierarchy = new List<Type>();
        var currentType = GetType();
        
        // 遍历直到object基类(跳过object)
        while (currentType != typeof(object))
        {
            typeHierarchy.Add(currentType);
            currentType = currentType.BaseType;
        }
        
        // 反转顺序,得到从Item到当前类的继承链
        typeHierarchy.Reverse();
        
        // 拼接类名作为路径前缀
        var pathPrefix = string.Join("/", typeHierarchy.Select(t => t.Name));
        // 最终拼接prefabID
        itemPath = $"{pathPrefix}/{prefabID}";
    } 
}

优缺点:

  • ✅ 优点:完全自动化,新增子类(比如RangedWeapon)时不用修改任何现有代码,路径会自动适配继承链;类名修改时路径也会同步更新,减少人为错误。
  • ❌ 缺点:反射有轻微的性能开销,如果你的项目会频繁创建Item实例,可以考虑缓存每个类型的路径前缀(比如用静态字典存储Type到前缀的映射),避免重复计算。

方案2:手动重写虚方法(性能优先,无反射开销)

如果对性能要求很高,不想用反射,可以在每个子类中重写一个获取路径前缀的方法,手动拼接父类前缀+当前类名:

public class Item 
{ 
    public string itemPath; 
    public string prefabID; 

    // 基类返回自身类名作为前缀
    protected virtual string GetPathPrefix()
    {
        return nameof(Item);
    }

    protected void Initialize() 
    { 
        itemPath = $"{GetPathPrefix()}/{prefabID}";
    } 
}

public class Equippable : Item
{
    protected override string GetPathPrefix()
    {
        // 拼接父类前缀+当前类名
        return $"{base.GetPathPrefix()}/{nameof(Equippable)}";
    }
}

public class Weapon : Equippable
{
    protected override string GetPathPrefix()
    {
        return $"{base.GetPathPrefix()}/{nameof(Weapon)}";
    }
}

public class MeleeWeapon : Weapon
{
    protected override string GetPathPrefix()
    {
        return $"{base.GetPathPrefix()}/{nameof(MeleeWeapon)}";
    }
}

优缺点:

  • ✅ 优点:完全编译时确定路径,没有反射带来的性能损耗;逻辑直观,容易调试。
  • ❌ 缺点:新增子类必须记得重写GetPathPrefix,漏写会导致路径错误;类名修改时需要同步更新方法内的字符串(不过用nameof()可以避免硬编码问题)。

方案3:自定义特性+反射(支持自定义路径片段)

如果需要路径片段和类名不一致(比如类名是MeleeWeapon,但路径里想写Melee),可以用自定义特性标记每个类的路径片段,再通过反射读取拼接:

// 自定义特性,用于标记类对应的路径片段
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class PathSegmentAttribute : Attribute
{
    public string Segment { get; }
    public PathSegmentAttribute(string segment)
    {
        Segment = segment;
    }
}

[PathSegment("Item")]
public class Item 
{ 
    public string itemPath; 
    public string prefabID; 

    protected virtual void Initialize() 
    { 
        var typeHierarchy = new List<Type>();
        var currentType = GetType();
        
        while (currentType != typeof(object))
        {
            typeHierarchy.Add(currentType);
            currentType = currentType.BaseType;
        }
        
        typeHierarchy.Reverse();
        
        // 读取特性中的路径片段,没有则用类名
        var pathPrefix = string.Join("/", typeHierarchy.Select(t => 
        {
            var attr = t.GetCustomAttribute<PathSegmentAttribute>();
            return attr?.Segment ?? t.Name;
        }));
        
        itemPath = $"{pathPrefix}/{prefabID}";
    } 
}

[PathSegment("Equippable")]
public class Equippable : Item { }

[PathSegment("Weapon")]
public class Weapon : Equippable { }

// 这里路径片段用"Melee"代替类名"MeleeWeapon"
[PathSegment("Melee")]
public class MeleeWeapon : Weapon { }

优缺点:

  • ✅ 优点:灵活性极高,可以完全自定义每个类的路径片段,不受类名限制。
  • ❌ 缺点:同样有反射开销,且需要给每个类添加特性,维护成本比方案1高一些。

替代方案:用计算属性+缓存替代Initialize方法

如果不想显式调用Initialize方法,可以把itemPath改成计算属性,第一次访问时自动生成并缓存结果:

public class Item 
{ 
    public string prefabID; 
    private string _cachedItemPath;

    public string itemPath 
    { 
        get 
        { 
            if (_cachedItemPath == null)
            {
                var typeHierarchy = new List<Type>();
                var currentType = GetType();
                
                while (currentType != typeof(object))
                {
                    typeHierarchy.Add(currentType);
                    currentType = currentType.BaseType;
                }
                
                typeHierarchy.Reverse();
                var pathPrefix = string.Join("/", typeHierarchy.Select(t => t.Name));
                _cachedItemPath = $"{pathPrefix}/{prefabID}";
            }
            return _cachedItemPath;
        }
    }
}

这样你就不用再调用Initialize,直接访问itemPath就能得到正确的路径,而且缓存后只会计算一次,性能也有保障。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:37:46