我使用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));
答案 0 :(得分:0)
从评论中,听起来树中的根类型是字典。在DTO组件的静态分析期间,它无法识别这一点 - 因此不考虑KVP场景(其中存在无限多个)。您无需更改现有代码即可解决此问题 - 只需添加分析工具可以找到的内容即可。例如,如果将Dictionary<string, MyType>
序列化为根对象,则只需添加:
[ProtoContract]
public class NeverUsed {
[ProtoMember(1)]
public Dictionary<string,MyType> Dummy;
}
(现在重新运行protogen等)
这应该足以让静态分析工具找到它并准备适用于KeyValuePair<string,MyType>
的策略
另一种方法是始终将您自己的类型序列化为模型的根 - 主要从NeverUsed
实例开始。