【问题标题】:Can I deserialize an object when the underlying class has been changed slightly?当底层类发生轻微变化时,我可以反序列化一个对象吗?
【发布时间】:2011-05-10 11:41:15
【问题描述】:

我编写了一个自定义类MyClass 并用<Serializable()> 属性对其进行了标记。我的硬盘上有一组二进制文件,我使用来自MyClass 实例的BinaryFormatter 对其进行了序列化。

我最近稍微改变了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

【问题讨论】:

    标签: vb.net visual-studio-2010 serialization deserialization binaryformatter


    【解决方案1】:

    过去,我在使用 binaryformatter 对序列化对象进行细微更改之间遇到了兼容性问题,我也不完全理解为什么。有一种“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
    

    【讨论】:

    • 还有一点要提的。 XML 可能不适合您的目的,因为我不知道它如何处理序列化中的“私人”数据。不用说这是一个与二进制序列化不同的过程。
    【解决方案2】:

    您需要控制序列化和反序列化过程。 您可以使用ISerializable 接口来执行此操作。

    看看:

    http://msdn.microsoft.com/en-us/library/ty01x675.aspx“实现 ISerializable 接口”部分中有一些有用的信息

    【讨论】:

      【解决方案3】:

      添加和删除字段不应该有任何问题 - 我有经验证明,而不是我知道序列化的详细工作原理。

      更改私有属性的名称时可能会遇到问题。所有其他事情,甚至重新排序字段,你都很棒。

      【讨论】:

      • 如果删除字段,如果序列化数据中存在该属性,则会出现错误。添加字段应该没问题。您也不能更改程序集版本 # 或强命名键,因为这些也会导致反序列化失败。
      • @罗伯特。你完全错了。如果要求每个属性都以序列化格式存在,那么我们将不会有像 [IgnoreDataMember] 这样的数据协定属性。
      • 这是二进制序列化。当您提到 XML 序列化时您是正确的,但是如果您在序列化后从对象中删除属性,则二进制序列化将在反序列化时失败。
      • @Robert - 根据经验,从来没有遇到过这个问题。
      【解决方案4】:

      我还没有看过 BinaryFormatter.Deserialize() 的实际实现,所以我来推测一下。

      我不认为反序列化器有责任确保一个类的所有属性都不为空。在很多情况下,null 属性都是完全有效的并且不会导致任何问题。

      现在我可以回答你的问题了:

      我相信向类添加属性不会导致问题,但是我确实认为删除您尝试反序列化的属性会导致错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多