问题描述:

I am trying to serialize a class and then de-serialize it to a second class, to imitate future additions to the structure of the class, so I am attempting to Imlpement ISerializable

Imports System.IO

Imports System.Runtime.Serialization

Imports System.Runtime.Serialization.Formatters.Binary

<Serializable()> _

Public Class Serial

Implements ISerializable

Public Num1 As Integer

Public Num2 As Integer

Protected Sub New(ByVal Info As SerializationInfo, ByVal Context As StreamingContext)

With Info

Num1 = .GetInt32("Num1")

Num2 = .GetInt32("Num2")

End With

End Sub

Public Sub GetObjectData(info As System.Runtime.Serialization.SerializationInfo, context As System.Runtime.Serialization.StreamingContext) Implements System.Runtime.Serialization.ISerializable.GetObjectData

With info

.FullTypeName = "ObjectSerialization. Serial"

.AddValue("Num1", Num1)

.AddValue("Num2", Num2)

End With

End Sub

End Class

<Serializable()> _

Public Class Serial2

Implements ISerializable

Public Num1 As Integer

Public Num2 As Integer

Public Num3 As Integer

Protected Sub New(ByVal Info As SerializationInfo, ByVal Context As StreamingContext)

With Info

Num1 = .GetInt32("Num1")

Num2 = .GetInt32("Num2")

Num3 = .GetInt32("Num3")

End With

End Sub

Public Sub GetObjectData(info As System.Runtime.Serialization.SerializationInfo, context As System.Runtime.Serialization.StreamingContext) Implements System.Runtime.Serialization.ISerializable.GetObjectData

With info

.FullTypeName = "ObjectSerialization. Serial"

.AddValue("Num1", Num1)

.AddValue("Num2", Num2)

.AddValue("Num3", Num3)

End With

End Sub

End Class

An exception occurs (Unable to load type ObjectSerialization. Serial required for deserialization) when I attempt to deserialize in the code below. Can someone point me in the right direction.

Dim s1 As New Serial

Dim s2 As New Serial2

s1.Num1 = 99

s1.Num2 = 500

Dim fs As New FileStream("DataFile.dat", FileMode.Create)

Dim formatter As New BinaryFormatter

Try

formatter.Serialize(fs, s1)

Catch ex As SerializationException

Console.WriteLine("Failed to serialize. Reason: " & ex.Message)

Finally

fs.Close()

End Try

fs = New FileStream("DataFile.dat", FileMode.Open)

Try

formatter = New BinaryFormatter

s2 = formatter.Deserialize(fs)

Catch ex As SerializationException

Console.WriteLine("Failed to deserialize. Reason: " & ex.Message)

Throw

Finally

fs.Close()

End Try

End Sub

网友答案:

Have you tried to remove the space in ObjectSerialization. Serial and just use ObjectSerialization.Serial ?

Your code worked on my machine after this change and adding a public argumentless constructor

You could also do the following:

Try
    formatter = New BinaryFormatter
    Dim tmp As Serial = formatter.Deserialize(fs)
    s2.Num1 = tmp.Num1
    s2.Num2 = tmp.Num2
Catch ex As SerializationException

    Console.WriteLine("Failed to deserialize. Reason: " & ex.Message)
    Throw
Finally
    fs.Close()
End Try

Instead of copying the properties one by one, you could use a generic approach like this: http://www.codeproject.com/Articles/173664/Copy-Properties-From-One-Object-To-Another

网友答案:

I can get s1 = formatter.Deserialize(fs) to work just fine. s2 = formatter.Deserialize(fs) however fails every time.

Serial required for deserialization means you cannot deserialize object A into object B (Serial is the keyword and is referring to your Class name). The MS binary serializer requires that you deserialize into the same class-culture-assembly object which serialized the data. When MS serializes the class-culture-assembly info is part of the binary data. There are ways around this such as writing a serializing service (like in a DLL) and other things, but there is no direct way.

If you are looking for a sort of data exchange serializer, look at ProtoBuf-NET. It is both faster than MS and produces MUCH MUCH smaller output (an empty dictionary goes from 3000 to 300 bytes). PBN is easy to use and will allow you to do what the post text (de-serialize it to a second class) describes. In fact the syntax is almost the same.

EDIT

OK, I am not sure what 'Serial' refers to in this case. I changed the class names and get the same error, so it might be related to the use of Interfaces (which do seem like a way around deserializing into a different type object). When I tried to exchange data between 2 types the message gave me something along the lines of "myclass-english blah blah blah-myassembly' cannot deserialize to "myclass2-english-blah blah blah-otherassembly'.

AHA!

Change the classes to really simple ones without the ISerializable:

Public Class fromClass


Public Num1 As Integer
Public Num2 As Integer

Public Sub New()

End Sub

End Class

The public members work the same as if they were wrapped in property getters/setters (abd there is no reason this would not work). Now, when you try to deserialize to S2, there is a new message: Unable to cast object of type 'WindowsApplication1.fromClass' to type 'WindowsApplication1.toCLass'.

ISerializable is obscuring the issue. You cant deserialize into something else. Look at the text of the output file - the class-culture-assembly info is there (and is where your original err message was coming from). I think at least part of the reason for this is that Reflection is used in serialization; if it isnt going back into the same thing, it wont try (though it SEEMS like using an interface should work). Another reason is maybe security. PBN is much more clever and flexible and more or less designed around data exchange.

相关阅读:
Top