嵌套类的 Protobuf-net 错误:'Type is not expected, and no contract can be inferred: ...'



我正在使用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.* 中,它是选择加入。所以:最好是明确的。

相关内容

最新更新