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

如何在未知类型时遍历List<>并递归序列化集合元素?

修复List<>类型属性的递归序列化问题

你的代码存在两个核心问题,导致List类型的属性无法正确遍历元素序列化:

  1. List类型判断错误:typeof(List<>)是开放泛型类型,而实际属性的类型是封闭泛型(比如List<int>),直接用==判断永远不成立。
  2. WriteCollectionPropertyToWriter逻辑完全错误:你现在是在遍历PropertyInfo自身的属性,而不是获取列表中的元素进行序列化。

修改后的完整代码

public class NetworkPacketSerializer
{
    public static IEnumerable<byte> SerializeToBytes(object packet)
    {
        var writer = new NetworkPacketWriter();
        var properties = packet.GetType().GetProperties();

        var identifierAttribute = packet.GetType().GetCustomAttribute<PacketIdAttribute>();

        if (identifierAttribute == null)
        {
            throw new InvalidOperationException($"Missing packet identifier attribute for packet type {packet.GetType()}");
        }
        
        writer.WriteShort(identifierAttribute.I);
        
        foreach (var property in properties)
        {
            // 只处理带PacketDataAttribute的属性,匹配原代码过滤逻辑
            if (Attribute.IsDefined(property, typeof(PacketDataAttribute)))
            {
                WriteProperty(property, writer, packet);
            }
        }

        return writer.GetAllBytes();
    }

    private static void WriteCollectionPropertyToWriter(PropertyInfo propertyInfo, NetworkPacketWriter writer, object packet)
    {
        // 获取列表的实际实例
        var list = propertyInfo.GetValue(packet) as IEnumerable;
        if (list == null) return;

        // 先写入列表长度,方便反序列化时读取
        writer.WriteInteger(list.Cast<object>().Count());

        // 遍历列表中的每个元素
        foreach (var item in list)
        {
            if (item == null) continue;
            
            var itemType = item.GetType();
            // 基础类型/字符串直接调用对应写入方法
            if (itemType == typeof(string))
            {
                writer.WriteString((string)item);
            }
            else if (itemType == typeof(int))
            {
                writer.WriteInteger((int)item);
            }
            else if (itemType == typeof(short))
            {
                writer.WriteShort((short)item);
            }
            // 自定义类则递归序列化其属性
            else
            {
                foreach (var prop in itemType.GetProperties().Where(p => Attribute.IsDefined(p, typeof(PacketDataAttribute))))
                {
                    WriteProperty(prop, writer, item);
                }
            }
        }
    }

    private static void WriteProperty(PropertyInfo property, NetworkPacketWriter writer, object packet)
    {
        var propertyType = property.PropertyType;
        var value = property.GetValue(packet);
        if (value == null) return;

        if (propertyType == typeof(string))
        {
            writer.WriteString((string)value);
        }
        else if (propertyType == typeof(int))
        {
            writer.WriteInteger((int)value);
        }
        else if (propertyType == typeof(short))
        {
            writer.WriteShort((short)value);
        }
        // 正确识别所有List<T>泛型类型
        else if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>))
        {
            WriteCollectionPropertyToWriter(property, writer, packet);
        }
        // 可按需扩展其他类型的处理逻辑
    }
}

关键修改说明

  • 修正List类型判断:通过IsGenericType结合GetGenericTypeDefinition(),准确识别所有List<T>封闭泛型类型。
  • 重构集合处理逻辑:先获取列表实例,写入列表长度(反序列化时必须的标记),再逐个遍历元素,根据元素类型选择直接写入或递归序列化属性。
  • 统一属性过滤:在根序列化方法中只处理带PacketDataAttribute的属性,避免序列化无关字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:54:53