如何识别导致二进制序列化在 .NET 中失败的字段

本文关键字:NET 序列化 失败 字段 二进制 何识别 识别 | 更新日期: 2023-09-27 18:36:53

我正在尝试使用以下方法在 .NET 中序列化对象图:

public static byte[] Serialize(object data)
{
    var binary = new BinaryFormatter();
    using (var ms = new MemoryStream()) {
        binary.Serialize(ms, data);
        return ms.ToArray();
    }
}

但是,我遇到了以下错误:

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)

有没有一种简单的方法来确定哪个字段产生了此错误?我可以递归地将对象图中的字段标记为非序列化以缩小潜在的罪魁祸首的范围,但由于对象图非常广泛,这很繁琐,似乎没有必要。

请注意,我不确定为什么二进制格式化程序无法序列化对象图中的一个或多个值。如果对象可以在运行时存储在内存中,则不清楚为什么无法序列化它。这可能是枚举的问题吗?

如何识别导致二进制序列化在 .NET 中失败的字段

使用 Windbg。在此处下载(仅从安装程序中选择调试器。您不需要下载完整的 SDK)并启动它。

然后使用File - Open Executable - 并启动它。您将在调试器中出现异常时中断。如果未选择,请在开始之前选择

Debug - Event Filters - CLR Exception - Enabled

在每个托管异常上启用断点。然后你需要输入

.loadby sos clr 
(if you are using .NET 3.5 .loadby sos mscorwks)
.prefer_dml 1
!dso

这将为您提供一个列表,其中包含当前线程在失败之前使用的对象。然后,单击带下划线的蓝色 NameInfo 实例之一,以查看序列化程序在哪个成员变量上失败。我同意学习需要一些耐心,但是您可以在创纪录的时间内调试这些东西,而其他人则需要在他们的代码中摆弄以解决问题。您需要做的就是查看确实导致问题的NameInfo实例。

我处理这个问题的方法是将对象序列化为字符串,然后将字符串写入文件。然后,您可以查看序列化字符串,查看它停止的位置,并从那里推断是哪个元素导致了问题。

注释

掉所有属性,并序列化对象。一次重新引入一个,直到错误返回。

这是基本调试。

但是,如果没有许多类型被序列化,堆栈跟踪会提供提示。