使用 protobuf-net 反序列化字典

Posted

技术标签:

【中文标题】使用 protobuf-net 反序列化字典【英文标题】:Deserialize Dictionary with protobuf-net 【发布时间】:2015-03-12 12:34:16 【问题描述】:

由于 BinaryFormatter 给我在 ios 上序列化字典带来了麻烦,我决定切换到 protobuf-net。并使用它来序列化我的 Unity3d 游戏中的内容。这是一些代码: 这是保存所有数据的类:

using System;
using System.Collections.Generic;
using ProtoBuf;
using UnityEngine;
namespace SerializationLib

    [ProtoContract]
   public class GameData
    
        [ProtoMember(1)]
        public int _coinAmount ;
        [ProtoMember(2)]
        public int _upgradeLevel;
        [ProtoMember(3)]
        public Level_Data[] _level_Data;
        [ProtoMember(4)]
        public CharacterUpgradeList _charUpgradeList;
        [ProtoMember(5)]
        public SerialVector2 serialVector;



    
    [ProtoContract]
    public class CharacterUpgradeList
    


        private List<UpgradeData>[] upgData;
        [ProtoMember(1,OverwriteList = true)]
        public Dictionary<string, List<UpgradeData>> upgradeList;

        public CharacterUpgradeList()
        
            upgData = new List<UpgradeData>[4];
            for (int i = 0; i < upgData.Length; i++)
            
                upgData[i] = new List<UpgradeData>  
                        new UpgradeData(),
                        new UpgradeData(),
                        new UpgradeData(),
                        new UpgradeData(),
                        new UpgradeData(),
                        new UpgradeData()
                   ;
            

            upgradeList = new Dictionary<string, List<UpgradeData>>
        
            "Man",upgData[0],
            "Woman",upgData[1],
            "Boy",upgData[2],
            "Girl",upgData[3]

        ;
        
    


    [ProtoContract]
    public class Level_Data
    
        [ProtoMember(1)]
        public int completion_status;
        [ProtoMember(2)]
        public int star_Rating;
    
    [ProtoContract]
    public class UpgradeData
    
        [ProtoMember(1)]
        public bool lockStatus;
        [ProtoMember(2)]
        public bool purchased;

    
    [ProtoContract]
    public struct SerialVector2
    
        [ProtoMember(1)]
        public float x;
        [ProtoMember(2)]
        public float y;

        public SerialVector2(Vector2 vect)
        
            x = vect.x;
            y = vect.y;
        
        public Vector2 returnVector2()
        
            return new Vector2(x, y);
        
    



这是我正在使用的数据序列化器

using System;
using System.Collections.Generic;
using SerializationLib;
using ProtoBuf.Meta;

namespace DataSerializer

    class Program
    
        static void Main(string[] args)
        
            var Model = TypeModel.Create();
            Model.Add(typeof(GameData), true);
            Model.Add(typeof(CharacterUpgradeList), true);
            Model.Add(typeof(Level_Data), true);
            Model.Add(typeof(UpgradeData), true);
            Model.Add(typeof(SerialVector2), true);

            Model.AllowParseableTypes = true;
            Model.AutoAddMissingTypes = true;

            Model.Compile("DataSerializer", "DataSerializer.dll");
        
    

这是一个 protobuf 包装器,可在我的其他 c# 脚本中统一使用

using UnityEngine;
using System.IO;

public static class ProtoWraper 

    private static DataSerializer m_serialiezer = new DataSerializer();


    public static T LoadObjectFromResources<T>(string resourcePath)
    
        TextAsset objectAsset = Resources.Load(resourcePath, typeof(TextAsset)) as TextAsset;
        if (objectAsset == null)
        

            return default(T);
        
        T deserializedObject = default(T);
        using (MemoryStream m = new MemoryStream(objectAsset.bytes))
        
            deserializedObject = (T)m_serialiezer.Deserialize(m, null, typeof(T));
        
        return deserializedObject;
    
    public static T LoadObjectFromPath<T>(string path)
    
        if (!File.Exists(path))
        
            return default(T);
        
        T deserializedObject = default(T);
        using(FileStream f = new FileStream(path,FileMode.Open))
        
             deserializedObject = (T)m_serialiezer.Deserialize(f,null,typeof(T));
        
        return deserializedObject;
    
    public static void SaveObjectToPath<T>(string objectPath, string filename, T serializedObject)
    
        if (!Directory.Exists(objectPath))
        
            Directory.CreateDirectory(objectPath);
        
        using (FileStream f = new FileStream(objectPath + filename, FileMode.OpenOrCreate))
        
            m_serialiezer.Serialize(f, serializedObject);
        
    

现在的问题是当我打电话给data = ProtoWraper.LoadObjectFromPath&lt;GameData&gt;(filename); 我得到ArgumentException: An element with the same key already exists in the dictionary.

【问题讨论】:

【参考方案1】:

没关系,我是个彻头彻尾的白痴,在更改 Serializationlib 后没有重新编译数据序列化程序:D。现在一切都好。

【讨论】:

以上是关于使用 protobuf-net 反序列化字典的主要内容,如果未能解决你的问题,请参考以下文章

了解 Protobuf-net 属性的序列化和反序列化

我可以使用 protobuf-net 在 Mono 中序列化一个对象(包含成员:​​字典、列表...等)并在 MS.NET 中反序列化它,反之亦然?

使用 protobuf-net 反序列化不同的列表

使用 ProtoBuf-Net,如何(反)序列化多维数组?

protobuf-net 反序列化错误 无效标签:0

Protobuf-Net 总是反序列化一个空列表