Serializing .NET objects is the easiest serialization
mode. In this particular scenario you need a file stream where you have
to place data and a formatter establishing the serialization mode. When
you have the formatter instance, you simply invoke the Serialize method. The System.Runtime.Serialization.Formatters namespace provides two sub namespaces, Binary and Soap, exposing respectively the following formatters: BinaryFormatter and SoapFormatter.
The first one serializes objects in a binary way. It is efficient but
you should use it only if you are sure that your objects will be
deserialized by .NET applications, because such binary format is not
universal. If you instead want to be sure that your objects can be
shared across different applications and platforms, you should prefer
the SoapFormatter that produces an Xml-based result useful when working with Soap web services.
Binary Serialization
The following example shows how you can serialize a typed collection of strings into a file on disk using the BinaryFormatter class:
Dim stringSeries As New List(Of String) From
{"Serialization", "demo",
"with VB"}
Dim targetFile As New _
FileStream("C:\temp\SerializedData.dat",
FileMode.Create)
Dim formatter As New BinaryFormatter
formatter.Serialize(targetFile, stringSeries)
targetFile.Close()
formatter = Nothing
Note
The above code example requires Imports System.IO and Imports System.Runtime.Serialization.Formatters.Binary directives.
The code simply creates a new file named SerializedData.Dat
and puts the result of the binary serialization in the file. If you
examine the content of the file with the Windows Notepad, you can obtain
a result similar to what is shown in Figure 1.
You don’t effectively need
to know how your objects are serialized, but it is interesting to
understand what kind of information is placed into the target file, such
as the serialized type, assembly information, and the actual data. To
deserialize a binary file you simply invoke the BinaryFormatter.Deserialize method, as shown in the following code which you write right after the preceding example:
Dim sourceFile As New FileStream("C:\temp\SerializedData.dat",
FileMode.Open)
formatter = New BinaryFormatter
Dim data = CType(formatter.Deserialize(sourceFile),
List(Of String))
sourceFile.Close()
formatter = Nothing
'Iterates the result
For Each item In data
Console.WriteLine(item)
Next
Notice that Deserialize returns Object;
therefore, the result needs to be converted into the appropriate type
that you expect. If you run the preceding code you see on your screen
how the strings from the collection are correctly listed. This kind of
serialization is also straightforward because it enables serializing
entire object graphs. Moreover, you can use this technique against user
interface controls in Windows Forms and WPF applications to persist the
state of your interface objects that can be later re-created.
Remember to perform serialization and deserialization operations within a Try..Catch block and implement code for handling the SerializationException exception that provides information on serialization/deserialization errors.
|
Creating Objects Deep Copies with Serialization
The code in Listing 1 shows how to accomplish this by implementing a generic method.
Listing 1. Implementing Deep Copy with Serialization
Imports System.Runtime.Serialization Imports System.Runtime.Serialization.Formatters.Binary Imports System.IO
Public Class CreateDeepCopy
Public Shared Function Clone(Of T)(ByVal objectToClone As T) As T
'If the source object is null, simply returns the current 'object (as a default) If Object.ReferenceEquals(objectToClone, Nothing) Then Return objectToClone End If
'Creates a new formatter whose behavior is for cloning purposes Dim formatter As New BinaryFormatter(Nothing, New StreamingContext( StreamingContextStates.Clone)) 'Serializes to a memory stream Dim ms As New MemoryStream Using ms formatter.Serialize(ms, objectToClone)
'Gets back to the first stream byte ms.Seek(0, SeekOrigin.Begin) 'Deserializes the object graph to a new T object Return CType(formatter.Deserialize(ms), T) End Using End Function End Class
|
Because you are not
limited to file streams, taking advantage of a memory stream is good in
such a scenario. You invoke the preceding method as follows:
Dim result As Object = CreateDeepCopy.Clone(objectToClone)
You could also implement extension methods for providing deep copy to all types.