Могу ли я десериализовать объект, когда базовый класс был немного изменен? - PullRequest
7 голосов
/ 10 мая 2011

Я написал собственный класс MyClass и пометил его атрибутом <Serializable()>.У меня на жестком диске есть набор двоичных файлов, которые я сериализовал с использованием BinaryFormatter, полученных из экземпляров MyClass.

. Недавно я немного изменил структуру MyClass (добавил несколькосвойства, удалил некоторые свойства, изменил несколько методов и т. д.).

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

Спасибо.


Вот код, который я использую для выполненияСериализация:

Public Sub serializeObject(ByVal obj As Object, ByVal outFilename As String)
    Dim fStream As FileStream
    Try
        fStream = New FileStream(outFilename, FileMode.Create)
        Dim bfmtr As New BinaryFormatter
        bfmtr.Serialize(fStream, obj)
        fStream.Close()
    Catch ex As Exception
        MsgBox("Failed to serialize: " & ex.Message)
        Throw
    End Try
End Sub

И для десериализации я использую:

myObj = CType(deserializeObject("C:\myobject.bin"), MyClass))

Где deserializeObject:

Public Function deserializeObject(ByVal srcFilename As String) As Object
    If File.Exists(srcFilename) Then
        Dim fStream As Stream = File.OpenRead(srcFilename)
        Dim deserializer As New BinaryFormatter
        Dim returnObject As Object = deserializer.Deserialize(fStream)
        fStream.Close()
        Return returnObject
    Else
        Throw New ApplicationException("File not found: " & srcFilename)
    End If
End Function

Ответы [ 4 ]

1 голос
/ 25 июня 2011

В прошлом у меня были проблемы с совместимостью между незначительными изменениями в сериализованных объектах, использующих двоичный форматер, и я также не до конца понимаю, почему. Существует метод «UnsafeDeserialize», который подразумевает более совместимую «десериализацию».

«Что происходит» - когда происходит изменение совместимости, вы просто не можете воссоздать объект. Я не знаю, есть ли способ воссоздать его, если не использовать старую структуру кода.

В этих случаях я использовал сериализацию XML, которая кажется намного более безопасной (и удобочитаемой, чтобы вы могли потенциально исправить любую проблему, возникшую у вас позже)

Стоимость заключается в том, что размер сериализованных объектов XML в большинстве случаев значительно больше. Сжатие / распаковка могут помочь этому.

Вот мои подпрограммы XML, которые я использую для этого.

''' <summary>
''' Serializes as object into XML format
''' This IS different then SOAP Serialization.
''' </summary>
''' <typeparam name="ObjectType">The type of the object being serialized</typeparam>
''' <param name="oObj">The object to serialize</param>
''' <returns>The XML Document (string) that is the serialized object in text form</returns>
Public Shared Function XmlSerialize(Of ObjectType)(ByVal oObj As Object) As String
    Dim sb As New System.Text.StringBuilder
    Dim sw As New IO.StringWriter(sb)
    Dim x As New System.Xml.Serialization.XmlSerializer(GetType(ObjectType))
    x.Serialize(sw, oObj)
    Return sb.ToString
End Function
''' <summary>
''' DeSerializes and object from an XML Document
''' This IS different then SOAP Serialization.
''' </summary>
''' <typeparam name="ObjectType">The Object type that will be returned (That the XML Data is derived from)</typeparam>
''' <param name="oObj">The Object (in it's XML Document serialized format)</param>
''' <returns>The new object</returns>
Public Shared Function XmlDeSerialize(Of ObjectType)(ByVal oObj As String) As ObjectType
    Dim sr As New IO.StringReader(oObj)
    Dim x As New System.Xml.Serialization.XmlSerializer(GetType(ObjectType))
    Dim out As ObjectType = CType(x.Deserialize(sr), ObjectType)
    Return out
End Function
1 голос
/ 26 июля 2011

Вам нужно будет контролировать процесс сериализации и десериализации. Для этого вы можете использовать интерфейс ISerializable .

Взгляните на:

http://msdn.microsoft.com/en-us/library/ty01x675.aspx, есть некоторая полезная информация в разделе «Реализация интерфейса ISerializable» .

0 голосов
/ 30 июля 2011

Я не смотрел на фактическую реализацию BinaryFormatter.Deserialize (), поэтому я буду размышлять.

Я не думаю, что десериализатор отвечает за то, чтобы все свойства класса не были нулевыми. Существует множество сценариев, в которых нулевые свойства полностью действительны и не вызывают проблем.

Теперь я могу ответить на ваш вопрос:

Я считаю, что добавление свойств в класс не вызовет проблем, однако я считаю, что удаление свойств, которые вы пытаетесь десериализовать, приведет к ошибкам.

0 голосов
/ 10 мая 2011

Добавление и удаление полей НЕ ДОЛЖНО быть проблемой - у меня есть эмпирическое доказательство этого, а не то, что я знаю, как сериализация работает подробно.

У вас могут возникнуть проблемы при изменении имени частных свойств. Все остальное, даже переупорядочение полей, ты крут.

...