У меня возникли проблемы с десериализацией умеренно сложных объектов, созданных путем сериализации из более поздней версии моей программы. Я получаю исключение:Deserializing BinaryFormatter Файлы с более ранней версией вызывают исключение SerializationException.
System.Runtime.Serialization.SerializationException was unhandled
Message=The ObjectManager found an invalid number of fixups. This usually indicates a problem in the Formatter.
Source=mscorlib
StackTrace:
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at Microsoft.Samples.TestV1.Main(String[] args) in c:\Users\andrew\Documents\Visual Studio 2013\Projects\vts\CS\V1 Application\TestV1Part2\TestV1Part2.cs:line 29
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
...
Это связано с попытками десериализации объектов, которые были изменены (добавлены члены) в более поздних версиях с более старой версией. Однако Microsoft заявляет, что она должна работать из-за VTS. См.: https://msdn.microsoft.com/en-us/library/ms229752(v=vs.110).aspx
Они представляют собой пример, который не изменен, действительно позволяет десериализовать более свежие классы с более старой версией. См: https://msdn.microsoft.com/en-us/library/7a6c3wzt(v=vs.110).aspx
Однако, как намекнул здесь: Deserialization backwards compatibility с комментарием,
kareph, what is the real type of Zoo ? I remember some types (arrays) just didn't work right.
- это не займет много, чтобы сделать вещи несовместимые. Я взял пример VTS от Microsoft (перечисленных выше), и добавил следующее к примеру V2 ApplicationCS под «Человек» класса:
[OptionalField(VersionAdded = 2)]
private List<HealthData> _healthDataList;
public List<HealthData> HealthDataList
{
get { return _healthDataList; }
set { _healthDataList = value; }
}
HealthData просто определяется как:
[Serializable]
public class HealthData
{
#region Fields
private int _weight;
private int _height;
#endregion
#region Properties
public int Weight
{
get { return _weight; }
set { _weight = value; }
}
public int Height
{
get { return _height; }
set { _height = value; }
}
#endregion
}
Этого достаточно, чтобы получить ужасное исключение "... недопустимое количество исправлений ...".
Любопытно, что если я просто добавлю список целых чисел, все будет хорошо. Я задавал следующие вопросы:
- Что вызывает десериализацию? Насколько сложной может быть структура класса до того, как все провалится? Очевидно, что достаточно класса, у которого есть список объектов, которые являются определенными пользователем классами. Что еще?
- Как я могу исправить ситуацию? Есть ли способ? Было бы неплохо узнать, что мы можем добавлять новых членов и иметь возможность читать новые сериализованные файлы со старыми копиями программного обеспечения.
- Этот пост: Deserialization backwards compatibility предлагает proto-buf.net как альтернативу. Будет ли это устранять проблему, которую я здесь изложил? Имеются ли ограничения?
Моя реальная структура класса совсем немного сложнее, чем, например Microsoft, но я, конечно, есть Массивы и списки <> классов, так что это хорошая вещь, чтобы рассмотреть в первую очередь. Но могут быть и другие «gotchas», которых нет в простом примере Microsoft.
Любые идеи или помощь будут высоко оценены.
Dave