编译的Unity构建中的Protobuf抛出InvalidOperationException:没有为类型定义的序列化程序

时间:2014-04-05 20:54:02

标签: c# unity3d protobuf-net

我使用protobuf-net为Unity加载一个级别的数据。序列化/反序列化在编辑器中运行时有效,但是当我编译并创建构建然后运行它时,我在反序列化时遇到以下异常:

InvalidOperationException: No serializer defined for type:
System.Collections.Generic.KeyValuePair`2[[System.String, 
    mscorlib, Version=2.0.5.0, Culture=neutral, 
    PublicKeyToken=7cec85d7bea7798e],[System.Int32, mscorlib, Version=2.0.5.0, 
    Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]

我不能100%确定protobuf-net在使用它们进行反序列化之前如何分析类型,所以我不确定如何解决这个问题。如果有人知道可能导致这个问题的原因,我真的很感激解释。我可以自己定义反序列化方法吗?像某个类型的自定义反序列化器?谢谢!

修改

以下是我认为导致此问题的课程:

[ProtoContract]
public class LevelData
{
    [ProtoMember(1)]
    public string Background = "";
    [ProtoMember(2)]
    public string Name = "";
    [ProtoMember(3)]
    public Dictionary<string, int> PreloadInfo {get; private set;}
    [ProtoMember(4)]
    public List<string> RoomFiles { get; private set; }

    public LevelData()
    {
        PreloadInfo = new Dictionary<string, int>();
        RoomFiles = new List<string>();
    }
}

运行protogen之后,我注意到Unity和我创建的已编译dll之间的String和Int32版本不匹配。 Unity尝试使用版本2.0.5.0反序列化,而我编译的dll使用版本2.0.0.0。我假设这就是反序列化失败的原因。这是protogen的输出:

Adding System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib,
  Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, msc
  orlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]...
  Adding System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib, Versi
  on=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, ms
  corlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]...

用于反序列化的代码:

var serializer = GnomingSerializer.Create ();

int startMillis = System.Environment.TickCount;

TextAsset levelDoc = (TextAsset)Resources.Load(path);
MemoryStream mStream = new MemoryStream(levelDoc.bytes);

//LevelData levelData = Serializer.Deserialize<LevelData>(mStream);
LevelData levelData = new LevelData();
serializer.Deserialize (mStream, levelData, typeof(LevelData));

1 个答案:

答案 0 :(得分:0)

从评论中,听起来树中的根类型是字典。在DTO组件的静态分析期间,它无法识别这一点 - 因此不考虑KVP场景(其中存在无限多个)。您无需更改现有代码即可解决此问题 - 只需添加分析工具可以找到的内容即可。例如,如果将Dictionary<string, MyType>序列化为根对象,则只需添加:

[ProtoContract]
public class NeverUsed {
    [ProtoMember(1)]
    public Dictionary<string,MyType> Dummy;
}

(现在重新运行protogen等)

这应该足以让静态分析工具找到它并准备适用于KeyValuePair<string,MyType>的策略

另一种方法是始终将您自己的类型序列化为模型的根 - 主要从NeverUsed实例开始。