У меня возникают проблемы с десериализацией умеренно сложных объектов, созданных сериализацией из более поздней версии моей программы. Я получаю исключение:
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
Однако, как указано здесь: Обратная совместимость десериализации с комментарием,
kareph, what is the real type of Zoo ? I remember some types (arrays) just didn't work right.
– не нужно многого, чтобы сделать вещи несовместимыми. Я взял пример Microsoft VTS (указанный выше) и добавил следующее в пример V2 ApplicationCS в классе «Person»:
[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
}
Этого достаточно, чтобы получить страшное исключение "...недопустимое количество исправлений...".
Любопытно, что если я просто добавлю список целых чисел, все будет хорошо. Мои вопросы:
- Что приводит к сбою десериализации? Насколько сложной может быть структура класса, прежде чем что-то пойдет не так? По-видимому, достаточно иметь класс со списком объектов, определяемых пользователем. Что еще?
- Как я могу все исправить? Есть ли способ? Было бы неплохо узнать, что мы можем добавлять новых членов и иметь возможность читать новые сериализованные файлы со старыми копиями программного обеспечения.
- Этот пост: Обратная совместимость десериализации предлагает proto-buf.net в качестве альтернативы. Будет ли это решать проблему, которую я изложил здесь? Есть ли у него ограничения?
Фактическая структура моего класса немного сложнее, чем в примере с Microsoft, но у меня, безусловно, есть классы Arrays и Lists‹>, так что это неплохо рассмотреть в первую очередь. Но могут быть и другие «подводные камни», которых нет в простом примере Microsoft.
Любые идеи или помощь будут высоко оценены.
Дэйв