Вопрос по c#, binaryformatter, .net, serialization – Как определить поле, которое вызывает сбой двоичной сериализации в .NET?

7

Я пытаюсь сериализовать граф объектов в .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)

Есть ли простой способ определить, какое поле вызывает эту ошибку? Я мог бы рекурсивно пометить поля в графе объектов как NonSerialized, чтобы сузить потенциальных преступников, но, поскольку графа объектов довольно обширна, это обременительно и кажется ненужным.

Обратите внимание, что я не уверен, почему BinaryFormatter не может сериализовать одно или несколько значений в графе объектов. Если объект может храниться в памяти во время выполнения, неясно, почему его нельзя сериализовать. Может ли это быть проблемой с перечислением?

Ваш Ответ

3   ответа
3

которым я подошел к этому, состоял в том, чтобы сериализовать объект в строку, а затем записать строку в файл. Затем вы можете посмотреть на сериализованную строку, увидеть, где она остановилась, и определить, какой элемент вызвал проблему.

Умно ... Я попробую. mcliedtk
6

Вот (выберите из установщика только отладчик. Вам не нужно загружать полный 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, который вызвал проблему.

Извините за долгую задержку в принятии этого. У меня никогда не было времени, чтобы проверить этот подход, но поскольку он дает представление о потенциально полезном инструменте, о котором я не знал, я думаю, что этот ответ является наиболее полезным / многообещающим. mcliedtk
Я использовал это для отладки больших изменений в сериализуемой модели данных, и это быстро указало мне правильное направление. Если у вас есть разрыв в правильном исключении, вы можете использовать! Clrstack -p, чтобы получить дамп трассировки стека с указателями на параметры. В моем случае у многих из них не было данных, но дальше по стеку он содержал указатель на сериализуемый объект.
-1

х по одному, пока ошибка не вернется.

Это базовая отладка.

Однако трассировка стека дает подсказки, если сериализовано не много типов.

@mcliedtk У меня была похожая проблема с сериализацией Json. Ответ был почти всегда & quot; Последнее добавленное вами поле / свойство & quot;
Да, это базовая отладка, и, возможно, я не совсем понял в своем первоначальном вопросе, но я жду альтернативы этому подходу. Граф объектов довольно широкий и глубокий, и я надеялся на быстрый путь. mcliedtk
Хорошая точка зрения. Я посмотрю в истории источников, чтобы увидеть, есть ли очевидные изменения, но, к сожалению, я имею дело с очень большим графом объектов, который охватывает много файлов, так что это может потребовать некоторого исследования. Спасибо за предложения. mcliedtk

Похожие вопросы