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

如何在C#中基于ISerializable实现Vector2[]的字节序列化?

解决C#中ISerializable处理复合字典结构的问题

针对你遇到的Dictionary<MyEnum, Vector2[]>手动序列化问题,有两种直接可行的方案,完全适配ISerializable的要求,同时避免键重复:

方案一:使用层级化唯一键名

通过给每个序列化项添加层级索引前缀,确保键名绝对唯一,完全贴合SerializationInfo的键值对存储逻辑。

序列化(GetObjectData方法)

public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    // 先存入字典元素总数
    info.AddValue("DictCount", dict.Count);
    
    int entryIndex = 0;
    foreach (var kvp in dict)
    {
        // 存储枚举键的ordinal值
        info.AddValue($"DictEntry_{entryIndex}_KeyOrdinal", (int)kvp.Key);
        // 存储当前数组的长度
        info.AddValue($"DictEntry_{entryIndex}_ArrayLength", kvp.Value.Length);
        
        // 逐个存储Vector2的X和Y
        for (int vecIndex = 0; vecIndex < kvp.Value.Length; vecIndex++)
        {
            var vec = kvp.Value[vecIndex];
            info.AddValue($"DictEntry_{entryIndex}_Vector_{vecIndex}_X", vec.X);
            info.AddValue($"DictEntry_{entryIndex}_Vector_{vecIndex}_Y", vec.Y);
        }
        
        entryIndex++;
    }
}

反序列化(专用构造函数)

protected MyClass(SerializationInfo info, StreamingContext context)
{
    dict = new Dictionary<MyEnum, Vector2[]>();
    int dictCount = info.GetInt32("DictCount");
    
    for (int entryIndex = 0; entryIndex < dictCount; entryIndex++)
    {
        // 读取枚举键
        var keyOrdinal = info.GetInt32($"DictEntry_{entryIndex}_KeyOrdinal");
        MyEnum key = (MyEnum)keyOrdinal;
        
        // 读取数组长度并初始化数组
        int arrayLength = info.GetInt32($"DictEntry_{entryIndex}_ArrayLength");
        Vector2[] vecArray = new Vector2[arrayLength];
        
        // 逐个读取Vector2的X和Y并赋值
        for (int vecIndex = 0; vecIndex < arrayLength; vecIndex++)
        {
            float x = info.GetSingle($"DictEntry_{entryIndex}_Vector_{vecIndex}_X");
            float y = info.GetSingle($"DictEntry_{entryIndex}_Vector_{vecIndex}_Y");
            vecArray[vecIndex] = new Vector2(x, y);
        }
        
        dict.Add(key, vecArray);
    }
}

这种方式逻辑清晰,每个键都带有明确的层级索引,完全不会出现键重复的问题,后续扩展其他数组也只需延续相同的命名规则即可。

方案二:复刻Java的字节流写法

如果更习惯Java中直接写入原始数据的方式,可以把整个字典序列化为一个字节数组,再存入SerializationInfo,反序列化时再按顺序读取。

序列化(GetObjectData方法)

public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    using (var ms = new MemoryStream())
    using (var writer = new BinaryWriter(ms))
    {
        // 写入字典元素数
        writer.Write(dict.Count);
        
        foreach (var kvp in dict)
        {
            // 写入枚举ordinal
            writer.Write((int)kvp.Key);
            // 写入数组长度
            writer.Write(kvp.Value.Length);
            
            // 逐个写入Vector2的X和Y
            foreach (var vec in kvp.Value)
            {
                writer.Write(vec.X);
                writer.Write(vec.Y);
            }
        }
        
        // 将字节数组存入SerializationInfo
        info.AddValue("DictRawData", ms.ToArray());
    }
}

反序列化(专用构造函数)

protected MyClass(SerializationInfo info, StreamingContext context)
{
    dict = new Dictionary<MyEnum, Vector2[]>();
    byte[] rawData = (byte[])info.GetValue("DictRawData", typeof(byte[]));
    
    using (var ms = new MemoryStream(rawData))
    using (var reader = new BinaryReader(ms))
    {
        int dictCount = reader.ReadInt32();
        
        for (int i = 0; i < dictCount; i++)
        {
            // 读取枚举键
            MyEnum key = (MyEnum)reader.ReadInt32();
            // 读取数组长度
            int arrayLength = reader.ReadInt32();
            
            Vector2[] vecArray = new Vector2[arrayLength];
            for (int j = 0; j < arrayLength; j++)
            {
                float x = reader.ReadSingle();
                float y = reader.ReadSingle();
                vecArray[j] = new Vector2(x, y);
            }
            
            dict.Add(key, vecArray);
        }
    }
}

这种方式完全和你熟悉的Java逻辑一致,不需要担心键的问题,所有数据打包成一个字节数组存储,缺点是序列化后的内容可读性差,但性能和简洁性更好。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 16:25:18