c# - 嵌套类的 Protobuf-net 错误:'类型不是预期的,并且无法推断出任何合同:...'
问题描述
我正在使用 Protobuf-net v2.4.4 序列化一系列包含大型双数组的嵌套类。除了自定义类之外,所有数据类型都是原语或原语数组/列表,例如字符串或 double[],我不确定为什么会收到此错误。该错误似乎也随机出现在我的课程中。一个类可以很好地序列化 - 重新启动后,它会停止工作并抛出上述错误。我还能够在一个新项目中序列化一个类,但不能在我的原始项目中。有什么好的方法来调试它并找到它的来源吗?我怀疑这是某种项目设置或冲突的 DLL,因为新项目的引用显然要少得多。
我开始自行序列化每个自定义类以追踪问题,但鉴于上述经验,我不确定这是否可靠。不过,我在下面粘贴了我的代码的简化示例。有问题的类是 MyClass2 -> MyClass5 和 MyClass3。但是我在这些课程中看不到任何不寻常的东西。
任何建议将不胜感激。
[ProtoContract] public class MyParentClass
{
[DataMember] [ProtoMember(1)] public MyClass1 Settings { get; set; } // On its own this class serializes fine
[DataMember] [ProtoMember(2, OverwriteList = true)] public List<MyClass2> Zones { get; set; } = new List<MyClass2>(); // ProtoBuf does not like this class
...
[DataMember] [ProtoMember(4)] public MyClass3 Results { get; set; } // This serializes fine in one project but not in conjunction with the rest here
}
[ProtoContract] public class MyClass2
{
[DataMember] [ProtoMember(5)] public MyClass4 Settings { get; set; } // On its own this class serializes fine
[DataMember] [ProtoMember(6, OverwriteList = true)] public List<MyClass5> faces { get; set; } = new List<MyClass5>(); // ProtoBuf does not like this one
[DataMember] [ProtoMember(7)] public MyClass6 Result { get; set; } // This class looks similar to MyClass3
...
}
[ProtoContract] public class MyClass5
{
[DataMember] [ProtoMember(4)] public Enum1 Bcond { get; set; } = Enum1._UNSET_; // These enums are also decorated with ProtoContract and ProtoEnum
...
[DataMember] [ProtoMember(7)] public string Twin { get; set; } = "";
...
}
[ProtoContract] public class MyClass3
{
[DataMember] [ProtoMember(1)] public double energy { get; set; }
...
[DataMember] [ProtoMember(3, OverwriteList = true)] public double[] MoreEnergy { get; set; } = new double[8760];
...
[DataMember] [ProtoMember(17, OverwriteList = true)] public double[] EvenMoreDataButNotSetAutomatically { get; set; }
}
解决方案
从根本上说,我无法重现您所看到的;获取上面的代码并在本地使用它,它就可以工作。
然而!如果您同时开始序列化类型,则可能会出现一些奇怪的时序场景 - 通常在 Web 服务器等上。这里的一个很好的解决方法是确保所有准备工作尽早发生,例如在您可以执行的启动代码中:
Serializer.PrepareSerializer<MyParentClass>();
(也许还有其他几个)
请注意,这new double[8760]
是一个坏主意,因为 protobuf-net 将运行构造函数,然后交换数组;您可能想要推迟它并在您自己的代码中创建它(或者可以使用各种其他技巧)。您可能还想为此使用“打包”数组,即
[ProtoMember(3, OverwriteList = true, IsPacked = true)]
在MoreEnergy
财产上。
在 v3 中,“打包”编码在适用时默认启用,因此它本质上是选择退出;在 v2.* 中,它是可选的。所以:最好是明确的。
推荐阅读
- c# - 在存储库中使用 ThenInclude() 方法
- discord.py - 每次有人使用命令时如何在数字上加 + 1
- python - 如何从python中没有空格的字符串中提取数据
- python-3.x - Spacy lemmatization:单词“number”的错误结果
- python - 如何通过venv指定用于创建虚拟环境的python版本?
- python - 用 Python 绘制从 excel 导入的相关表
- delphi - 使用 RTTI 从已知类型在 Delphi 中设置 TValue 记录
- augmented-reality - ARKit - 测量单位的官方来源?
- gtk - gtk height_for_width 由于最小宽度较小,导致给定宽度的窗口高度不合理
- powershell - 如何在 powershell 脚本中为每个当前用户添加 HKCU Regkeys 值?