【问题标题】:Sporadic serialization failure in C#C# 中的零星序列化失败
【发布时间】:2025-11-24 20:25:04
【问题描述】:

我们将 Excel 导入到我们的系统中,并进行了非常严格的测试。最近,我们注意到零星的序列化错误。

这些错误在我们针对导入的自动化测试中出现,一遍又一遍地使用同一个文件。如果我们每次都收到这个错误,我会理解,但同样的序列化过程可能会失败一次而不是下一次,这似乎很奇怪。

Exception: FormatException: Input string was not in a correct format.
Stack Trace:
  at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
  at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
  at System.String.System.IConvertible.ToInt32(IFormatProvider provider)
  at System.Convert.ToInt32(Object value, IFormatProvider provider)
  at System.Runtime.Serialization.Formatters.Binary.__BinaryWriter.WriteValue(InternalPrimitiveTypeE code, Object value)
  at System.Runtime.Serialization.Formatters.Binary.__BinaryWriter.WriteMember(NameInfo memberNameInfo, NameInfo typeNameInfo, Object value)
  at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo, Object data)
  at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteMembers(NameInfo memberNameInfo, NameInfo memberTypeNameInfo, Object memberData, WriteObjectInfo objectInfo, NameInfo typeNameInfo, WriteObjectInfo memberObjectInfo)
  at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteMemberSetup(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, String memberName, Type memberType, Object memberData, WriteObjectInfo memberObjectInfo)
  at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, String[] memberNames, Type[] memberTypes, Object[] memberData, WriteObjectInfo[] memberObjectInfos)
  at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
  at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
  at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)

【问题讨论】:

  • 这些是单元测试吗?您的任何测试是否修改了 Excel 文件?
  • 这些不是单元测试。这些是自动的浏览器内测试。没有测试修改excel文件,他们只是重复上传它们。我们在生产中也看到过几次错误,但它们似乎是一次性的,如果用户再试一次,似乎能够成功上传。
  • 很奇怪的堆栈跟踪。很难想象为什么格式化程序认为该成员是 int32 但实际上是一个字符串。对实际物体一无所知会导致猜测失败。
  • 我会添加一个额外的检查来查看整个文件是否在反序列化之前到达(长度和校验和)
  • re: Hans,对象图实在是太大了,不然我会贴出来的。

标签: c# serialization binary-serialization


【解决方案1】:

您是否有机会使用依赖反射的库将 Excel 文件映射到对象图?

例如,我在映射到文本文件时遇到了 Filehelpers 损坏数据的问题。不会经常发生,但确实会发生,而且只是间歇性的。

在这种情况下,FileHelpers 的问题在于 FileHelpers.RecordInfo.RecursiveGetFields(...) 依次调用 FileHelpers.FieldInfoCacheManipulator.ResetFieldInfoCache(...) ,后者使用反射来修改实际 .NET 反射的私有成员库,试图强制 .NET 反射按照声明的顺序返回字段。

但是,Microsoft 明确声明“您的代码不得依赖于返回字段/属性的顺序”http://msdn.microsoft.com/en-us/library/kyaxdd3x.aspxhttp://msdn.microsoft.com/en-us/library/6ztex2dc.aspx

如果您正在使用执行类似操作的库,它会解释您的间歇性错误,因为该库可能会将反序列化与不正确的源属性/字段不匹配,这可能是不同的类型。

【讨论】:

  • 我们使用反射映射到一组中间对象,然后将其序列化。关于字段/属性顺序的有趣注释。通过这个过程,我认为我们意识到 BinaryFormatter 太脆弱并且容易出错。只考虑 XML 序列化或 protobuf (code.google.com/p/protobuf-net)
最近更新 更多