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

如何在数据结构中隐式设置父子成员引用

解决方案:自动初始化DataStructure层级的父子引用

核心思路

利用初始化阶段的一次性反射遍历整个层级结构,自动设置Parent引用,并将子类别、属性分别填充到对应列表中。这样既避免了重复编写属性名称的维护问题,又保证了运行时的高效性。

步骤1:优化基础类定义

首先完善Category的构造函数,提前初始化SubCategories和Properties列表,避免空引用问题:

public interface IDataStructureMember
{
    public ICategory Parent { get; set; }
}

public interface ICategory : IDataStructureMember
{
    public List<ICategory> SubCategories { get; set; }
    public List<IDataProperty> Properties { get; set; }
}

public interface IDataProperty : IDataStructureMember { }

public abstract class Category : ICategory
{
    public ICategory Parent { get; set; }
    public List<ICategory> SubCategories { get; set; }
    public List<IDataProperty> Properties { get; set; }

    protected Category()
    {
        // 提前初始化列表,避免后续操作NullReferenceException
        SubCategories = new List<ICategory>();
        Properties = new List<IDataProperty>();
    }
}

public class DataProperty<T> : IDataProperty
{
    public ICategory Parent { get; set; }
    public T Value { get; set; }
}

步骤2:编写反射初始化工具类

创建一个静态工具类,递归遍历所有Category层级,自动设置父子关系并填充列表:

public static class StructureInitializer
{
    // 对外暴露的初始化入口,从根节点开始遍历
    public static void Initialize(ICategory root)
    {
        TraverseAndBindReferences(root, null);
    }

    private static void TraverseAndBindReferences(ICategory current, ICategory parent)
    {
        // 设置当前节点的父引用
        current.Parent = parent;

        // 获取当前类的所有公共实例属性
        var properties = current.GetType().GetProperties(
            System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);

        foreach (var prop in properties)
        {
            var value = prop.GetValue(current);
            if (value == null) continue;

            // 处理子类别(实现ICategory的属性)
            if (typeof(ICategory).IsAssignableFrom(prop.PropertyType))
            {
                var subCategory = (ICategory)value;
                current.SubCategories.Add(subCategory);
                // 递归处理子类别
                TraverseAndBindReferences(subCategory, current);
            }
            // 处理DataProperty(实现IDataProperty的属性)
            else if (typeof(IDataProperty).IsAssignableFrom(prop.PropertyType))
            {
                var dataProp = (IDataProperty)value;
                dataProp.Parent = current;
                current.Properties.Add(dataProp);
            }
            // 处理ICategory类型的列表(比如示例中的List<Force>)
            else if (prop.PropertyType.IsGenericType && 
                     prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
            {
                var elementType = prop.PropertyType.GetGenericArguments()[0];
                if (typeof(ICategory).IsAssignableFrom(elementType))
                {
                    var list = (IEnumerable)value;
                    foreach (var item in list)
                    {
                        var subCategory = (ICategory)item;
                        current.SubCategories.Add(subCategory);
                        TraverseAndBindReferences(subCategory, current);
                    }
                }
            }
        }
    }
}

步骤3:修改DataStructure触发初始化

在根类DataStructure的构造函数中调用初始化工具,完成整个层级的绑定:

public class DataStructure : Category 
{
    public EnvironmentData Environment { get; init; } = new();
    public ModelData Model { get; init; } = new();

    public DataStructure()
    {
        // 初始化时自动绑定所有父子引用
        StructureInitializer.Initialize(this);
    }

    // 内部类保持原定义不变
    public class EnvironmentData : Category
    {
        public LightData Light { get; init; } = new();
        public List<Force> Forces { get; init; } = new();

        public class LightData : Category
        {
            public LightPositionData LightPosition { get; init; } = new();
            public DataProperty<double> Intensity { get; init; } = new();

            public class LightPositionData : Category
            {
                public DataProperty<List<double>> OriginCoordsXYZ { get; init; } = new();
                public DataProperty<List<double>> TargetCoordsXYZ { get; init; } = new();
            }
        }
        public class Force : Category
        {
            public DataProperty<string> ForceName { get; init; } = new();
            public DataProperty<double> Magnitude { get; init; } = new();
        }
    }
    public class ModelData : Category
    {
        public DataProperty<string> ModelName { get; init; } = new();
        public DataProperty<string> ModelFilePath { get; init; } = new();

        public class ModelProperties : Category
        {
            public DataProperty<List<double>> BoundingBox { get; init; } = new();
        }
    }
}

验证效果

初始化后即可实现你需要的功能:

DataStructure newStructure = new();
// 获取LightData的所有属性
List<IDataProperty> envProperties = newStructure.Environment.Light.Properties; 
// 获取ModelName的父类别
ICategory p = newStructure.Model.ModelName.Parent; 

// 验证结果
Console.WriteLine(p == newStructure.Model); // 输出True
Console.WriteLine(envProperties.Contains(newStructure.Environment.Light.Intensity)); // 输出True

动态添加子项的处理

如果后续需要动态添加子类别(比如向Forces列表添加新元素),可以给Category添加一个辅助方法,手动绑定父子关系:

public class Category : ICategory
{
    // ... 原有代码

    public void AddSubCategory(ICategory subCategory)
    {
        subCategory.Parent = this;
        SubCategories.Add(subCategory);
    }
}

// 使用示例
newStructure.Environment.Forces.Add(new DataStructure.EnvironmentData.Force());
newStructure.Environment.AddSubCategory(newStructure.Environment.Forces.Last());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 08:25:24