Reputation: 11
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
Upvotes: 1
Views: 2554
Reputation: 38875
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.
Upvotes: 0
Reputation: 1225
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
Upvotes: 1