7

Escribí una clase personalizada MyClass y la marqué con el atributo <Serializable()>. Tengo un conjunto de archivos binarios en mi disco duro que he serializado utilizando BinaryFormatter que provienen de instancias de MyClass.¿Puedo deserializar un objeto cuando la clase subyacente se ha modificado ligeramente?

He cambiado recientemente la estructura de MyClass ligeramente (añadido algunas propiedades, eliminado algunas propiedades, cambiado algunos métodos, etc.).

¿Qué pasa cuando trato de deserializar los objetos existentes para esta clase cambiada utilizando el código de abajo? Lo he intentado y no me han arrojado un error ni nada, pero seguramente no se puede deserializar correctamente cuando la clase ha cambiado. ¿Hay alguna manera de obtener información útil de los archivos serializados aunque haya actualizado la clase?

Gracias.


Aquí está el código que estoy usando para hacer la serialización:

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 

Y para hacer la deserialización que estoy usando:

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

Dónde deserializeObject es:

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 

Respuesta

0

Añadiendo y eliminando los campos NO DEBERÍAN ser de ningún problema, tengo una prueba empírica de eso, no sé si la serialización funciona en detalle.

Usted podría tener problemas al cambiar el nombre de las propiedades privadas. Todas las demás cosas, incluso reordenando los campos, eres genial.

+0

Si quita campos, recibirá un error si existe la propiedad de los datos serializados. Agregar campos debería estar bien. Tampoco puede cambiar la versión de ensamblaje # o la clave de denominación fuerte, ya que también provocarán la deserialización. –

+0

@Robert. Estás completamente equivocado acerca de esto. Si se exigiera que cada propiedad existiera en el formato serializado, entonces no tendríamos atributos de contrato de datos como [IgnoreDataMember]. – BentOnCoding

+2

Esta es una serialización binaria. Tiene razón cuando se refiere a la serialización XML, pero la serialización binaria fallará en la deserialización si elimina una propiedad de un objeto después de la serialización. –

1

En el pasado he tenido problemas de compatibilidad entre los cambios de menor importancia en los objetos serializados utilizando el BinaryFormatter, y yo tampoco entiendo completamente por qué. Hay un método "UseguroDeserializar" que de algún modo implica un "deserializar" más compatible.

"qué sucede" es cuando se tiene un cambio de compatibilidad romper, simplemente no puede crear el objeto. No sé si hay alguna forma de volver a crearlo si no se utiliza una estructura de código antigua.

he utilizado serialización XML en estos casos lo que parece ser mucho más seguro (y se puede leer lo que potencialmente podría corregir cualquier problema que pueda tener más adelante)

El costo es que el tamaño de los objetos serializados XML es considerablemente más grande en la mayoría de los casos. Comprimir/descomprimir puede ayudar.

Éstos son mis rutinas XML que utilizo para esto.

''' <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 
+0

Algo más que mencionar. XML puede no ser adecuado para su propósito porque no sé cómo se trata con los datos "privados" en la serialización. No hace falta decir que es un proceso diferente a la serialización binaria. – DarrenMB

0

No he mirado en la aplicación real de BinaryFormatter.Deserialize() por lo que voy a especular.

No creo que es la responsabilidad del deserializer para asegurar que todas las propiedades de una clase no son nulos. Hay muchos escenarios donde las propiedades nulas son totalmente válidas y no causan problemas.

Ahora puedo responder a su pregunta:

Creo que la adición de las propiedades de una clase no causará problemas, sin embargo, creo que la eliminación de las propiedades que está intentando deserializar causará errores.

Cuestiones relacionadas