|
Another VB .NET XML Serialization Program Example
Create a new class library project. You can use the following project name and solution if you want.
Add/edit the following code. |
' This sample illustrates XML serialization. This sample illustrates using the ' XmlSerializer class. Additionally, this sample illustrates simple ' serialization as well as attribute and overriding serialization. The sample ' illustrates both serialization and deserialization from a file. Note however, ' a serialized file can only be deserialized using the same flags. That is if ' the flag "/override" was specified during serialization, it must also be present when deserializing. ' ' Usage: ' executable_file_name [/serialize | /deserialize] ' [/simple | /attribute | /override] [/file file.xml] ' /serialize Serialize data to XML ' /deserialize Deserialize data from XML ' /simple Perform simple XML serialization ' /attribute Perform XML serialization with attributes ' /override Perform XML serialization with overridden attributes ' /file filename File name to serialize to or deserialize from ' ' Sample usage: ' Simple XML serialization ' executable_file_name /serialize /simple /file simple.xml ' Simple XML deserialization ' executable_file_name /deserialize /simple /file simple.xml ' Serialize XML with overridden attributes ' executable_file_name /serialize /override /file override.xml ' Deserialize XML with overridden attributes ' executable_file_name /deserialize /override /file override.xml ' Imports System Imports System.IO Imports System.Xml.Serialization Imports System.Data
' Simple enumeration for the operation to perform: deserialization or serialization. Enum SerializeOperation opRead = 0 ' Deserialize opWrite = 1 ' Serialize End Enum
' Enumeration indicating which class to serialize. Enum SerializeClass classSimple = 0 classAttribute = 1 classOverride = 2 End Enum
' This is a simple helper class which creates a DataSet and initializes some data ' within it. The DataSet is an address book with two data columns: name and phone number. Public Class XmlAddressBookData Public Shared Function CreateAddressBook() As DataSet Dim addressBook As DataSet Dim friendsTable As DataTable Dim infoColumn As DataColumn Dim friendEntry As DataRow
' Create a collection, first create the dataset and then the table ' contained in the dataset Console.WriteLine("Creating a collection - An addressbook dataset and a table...") addressBook = New DataSet("AddressBook") friendsTable = New DataTable("Friends")
' Add columns to the data set Console.WriteLine("Adding columns...") infoColumn = New DataColumn("Name") friendsTable.Columns.Add(infoColumn) infoColumn = New DataColumn("Number") friendsTable.Columns.Add(infoColumn) addressBook.Tables.Add(friendsTable)
' Add a few entries to the collection Console.WriteLine("Adding some entries...") friendEntry = friendsTable.NewRow() friendEntry(0) = "Jim" friendEntry(1) = "867-5309" friendsTable.Rows.Add(friendEntry)
friendEntry = friendsTable.NewRow() friendEntry(0) = "Lance" friendEntry(1) = "555-4567" friendsTable.Rows.Add(friendEntry)
friendEntry = friendsTable.NewRow() friendEntry(0) = "Anthony" friendEntry(1) = "555-1234" friendsTable.Rows.Add(friendEntry)
CreateAddressBook = addressBook End Function
' Routine for displaying the contents of the address book. Public Shared Sub PrintAddressBook(ByVal addressBook As DataSet) Dim table As DataTable Dim row As DataRow
For Each table In addressBook.Tables For Each row In table.Rows Console.WriteLine("Name {0}: {1}", row("Name"), row("Number")) Next Next End Sub End Class
' Simple data structure to be serialize using the XML formatter. This structure contains a collection. Public Class MyXmlSimpleData Public CurrentDate As DateTime Public MyAddressBook As DataSet
Public DaysOfTheWeek() As String
' Private properties won't be serialized Private MySalary As Integer
' Default constructor for the MyXmlSimplData class which initializes ' the fields and builds a simple collection of names and phone numbers. Public Sub New() CurrentDate = DateTime.Today MySalary = 0 MyAddressBook = XmlAddressBookData.CreateAddressBook()
ReDim DaysOfTheWeek(7)
DaysOfTheWeek(0) = "Sunday" DaysOfTheWeek(1) = "Monday" DaysOfTheWeek(2) = "Tuesday" DaysOfTheWeek(3) = "Wednesday" DaysOfTheWeek(4) = "Thursday" DaysOfTheWeek(5) = "Friday" DaysOfTheWeek(6) = "Saturday" End Sub
' Simple method to set the private fields value. Public Sub SetSalary(ByVal data As Integer) MySalary = data End Sub
' Displays the values of all member variables including the collection. Public Sub Print() Console.WriteLine("MyXmlSimpleData.CurrentDate = {0}", CurrentDate) XmlAddressBookData.PrintAddressBook(MyAddressBook) Console.WriteLine("MyXmlSimpleData.MySalary = {0}", MySalary)
Dim i As Integer For i = 0 To DaysOfTheWeek.GetUpperBound(0) Console.WriteLine("DaysOfTheWeek[{0}] = {1}", i, DaysOfTheWeek(i)) Next End Sub
' This routine overrides the default serialization by changing the element name ' for a member variable when it is serialized. This is typically used when the ' same data needs to be serialized to XML with differing XML attributes. ' <param name="fileStream">The FileStream object to serialize the data to</param> Public Sub OverrideSerialization(ByVal fileStream As FileStream) Dim xmlElementAttribute As XmlElementAttribute = New XmlElementAttribute() Dim xmlAttributes As XmlAttributes = New XmlAttributes() Dim xmlAttributeOverrides As XmlAttributeOverrides = New XmlAttributeOverrides() Dim xmlSerializer As XmlSerializer = Nothing
' Override the element name for the "CurrentDate" property xmlElementAttribute.ElementName = "Override_Current_Date" xmlAttributes.XmlElements.Add(xmlElementAttribute) xmlAttributeOverrides.Add(GetType(MyXmlSimpleData), "CurrentDate", xmlAttributes)
' Serialize the class except specify the XmlAttributeOverrides object as well Console.WriteLine("Serializing an overridden class...") xmlSerializer = New XmlSerializer(GetType(MyXmlSimpleData), xmlAttributeOverrides)
Try xmlSerializer.Serialize(fileStream, Me) Catch err As System.InvalidOperationException Console.WriteLine("Serialization of overridden class failed: {0}", err.Message) End Try End Sub End Class
' This class illustrates declaring XML attributes along with the class definition. ' These attributes affect how the data is serialized to XML. Public Class MyXmlAttributeData <XmlElement("_1394Type")> _ Public FireWireType As Integer
<XmlArray("SupportedDevices"), XmlArrayItem("_1394Device")> _ Public SupportedDevices() As String
'Simple constructor to initialize member variables Public Sub New() FireWireType = 1
ReDim SupportedDevices(3) SupportedDevices(0) = "scanner" SupportedDevices(1) = "camcorder" SupportedDevices(2) = "mp3 player" End Sub
'Prints the class members to the console Public Sub Print() Console.WriteLine("MyXmlAttributeData.FireWireType = {0}", FireWireType) Dim i As Integer For i = 0 To SupportedDevices.GetUpperBound(0) Console.WriteLine("MyXmlAttributeData.SupportedDevices[{0}] = {1}", i, SupportedDevices(i)) Next End Sub End Class
' This is the main class which contains the Main function and other support routines. Class XmlSerializeSample
' Displays usage information Shared Sub usage() Console.WriteLine("Usage: executable_file_name [/serialize | /deserialize]") Console.WriteLine(" [/simple | /attribute | /override] [/file file.xml]") Console.WriteLine("...Else default settings will be used.") Console.WriteLine() End Sub
' Main routine that parses the command line, creates the select file stream, and ' serializes or deserializes the indicated class. ' <param name="args">Command line parameters passed to application</param> Shared Sub Main() Dim serializeOp As SerializeOperation = SerializeOperation.opWrite Dim serializeClass As SerializeClass = serializeClass.classSimple Dim fileName As String = "simpletestfile.xml"
usage() ' Parse the command line Dim args As String() = Environment.GetCommandLineArgs() Dim i As Integer
For i = 1 To args.Length - 1 If args(i) = "/serialize" Then serializeOp = SerializeOperation.opWrite ElseIf args(i) = "/deserialize" Then serializeOp = SerializeOperation.opRead ElseIf args(i) = "/file" Then Try i = i + 1 fileName = args(i) Catch e As System.IndexOutOfRangeException Console.WriteLine("Please specify output filename!") usage() End Try ElseIf args(i) = "/simple" Then serializeClass = serializeClass.classSimple ElseIf args(i) = "/attribute" Then serializeClass = serializeClass.classAttribute ElseIf args(i) = "/override" Then serializeClass = serializeClass.classOverride Else usage() Exit Sub End If Next
Dim fileStream As FileStream = Nothing Dim xmlSerializer As XmlSerializer = Nothing
' Create an instance of the FileStream on which serialization or deserialization ' will take place. If serializeOp = SerializeOperation.opWrite Then Dim s As String = "hello" Dim data() As Byte = System.Text.Encoding.ASCII.GetBytes(s.ToCharArray())
fileStream = New FileStream( _ fileName, _ FileMode.Create, _ FileAccess.Write, _ FileShare.None _ ) fileStream.Write(data, 0, 0) Console.WriteLine("Writing...")
ElseIf serializeOp = SerializeOperation.opRead Then fileStream = New FileStream( _ fileName, _ FileMode.Open, _ FileAccess.Read, _ FileShare.Read _ ) Console.WriteLine("Reading...") End If
If serializeOp = SerializeOperation.opWrite Then ' If serialization (writing) is selected, we need to create an instance ' of the class which will be serialized to the stream.
If serializeClass = serializeClass.classSimple Then ' Create an instance of the simple class Dim simpleData As MyXmlSimpleData = Nothing
simpleData = New MyXmlSimpleData() xmlSerializer = New XmlSerializer(GetType(MyXmlSimpleData))
Try Console.WriteLine("Serializing a simple class...") xmlSerializer.Serialize(fileStream, simpleData) Catch err As System.InvalidOperationException Console.WriteLine("Serialization of simple class failed: {0}", err.Message) End Try
ElseIf serializeClass = serializeClass.classAttribute Then
' Create an instance of the class containing XML attributes Dim attributeData As MyXmlAttributeData = Nothing
attributeData = New MyXmlAttributeData() xmlSerializer = New XmlSerializer(GetType(MyXmlAttributeData))
Try Console.WriteLine("Serializing an attributed class...") xmlSerializer.Serialize(fileStream, attributeData) Catch err As System.InvalidOperationException Console.WriteLine("Serialization of attributed class failed: {0}", err.Message) End Try
ElseIf serializeClass = serializeClass.classOverride Then ' Create an instance of the class which has its own override method ' and call that method to serialize the data. Dim simpleData As MyXmlSimpleData = Nothing
simpleData = New MyXmlSimpleData() simpleData.OverrideSerialization(fileStream) End If
ElseIf serializeOp = SerializeOperation.opRead Then ' If deserialization (reading) is selected, simply create an instance ' of the XmlSerializer for the type being serialized and call the deserialize method.
If serializeClass = serializeClass.classSimple Then Dim simpleData As MyXmlSimpleData = Nothing
xmlSerializer = New XmlSerializer(GetType(MyXmlSimpleData))
Try Console.WriteLine("Deserializing a simple class...") simpleData = xmlSerializer.Deserialize(fileStream)
Catch err As System.InvalidOperationException Console.WriteLine("Deserialization of simple class failed: {0}", err.Message) simpleData.Print() End Try
ElseIf ((serializeClass = serializeClass.classAttribute) Or (serializeClass = serializeClass.classOverride)) Then
Dim attributeData As MyXmlAttributeData = Nothing
xmlSerializer = New XmlSerializer(GetType(MyXmlAttributeData))
Try Console.WriteLine("Deserializing an attributed class...") attributeData = xmlSerializer.Deserialize(fileStream) attributeData.Print() Catch err As System.InvalidOperationException Console.WriteLine("Deserialization of attributed class failed: {0}", err.Message) End Try End If End If
' Close up Try Console.WriteLine("Closing a file stream...") fileStream.Close() Catch Console.WriteLine("Error closing FileStream...") End Try End Sub End Class |
Change the Application type: to Console Application and Startup object: to Sub Main.
|
Build and run the project. The following are sample outputs.
The generated XML file, simplexmlfile.xml as seen through browser is shown below.
As we mentioned earlier (program examples given at the beginning of this tutorial), SOAP is a standard based on XML for describing properties and methods. SOAP is used by Web services as well as .NET Remoting precisely for these abilities. In this sense, SOAP serialization is similar to remote procedure calls (RPCs) but is mainly concerned with standardizing message passing. SOAP provides a standard of describing these remote procedures and properties. The IFormatter interface described in the “Binary Serialization” section earlier in this chapter offers a way of generating SOAP messages by creating an instance of the SoapFormatter class.
You follow the same guidelines to use SoapFormatter as you do to use BinaryFormatter, as described in the “Binary Serialization” section. The only difference is that the IFormatter instance used is a SoapFormatter, that is, the class being serialized as well as any inherited classes must have the Serializable attribute set. The assembly containing the serialized object definition must be available at both the source and the destination. The serialized stream can also be customized in the same way by adding the NonSerialized attribute or by implementing the ISerializable interface, as you saw earlier. The following code serializes an object with the SoapFormatter:
C#
// Using the MyBasicData class defined earlier
MyBasicData basicData = new MyBasicData();
IFormatter soapFormatter = new SoapFormatter();
FileStream fileStream;
fileStream = new FileStream(
"soapformatter.xml",
FileMode.Create,
FileAccess.Write,
FileShare.None
);
soapFormatter.Serialize( fileStream, basicData);
Visual Basic .NET
Dim basicData As MyBasicData = New MyBasicData()
Dim soapFormatter As IFormatter = New SoapFormatter()
Dim fileDataStream As FileStream
fileDataStream = new FileStream( _
"soapformatter.cml", _
FileMode.Create, _
FileAccess.Write, _
FileShare.None _
)
soapFormatter.Serialize( fileDataStream, basicData )
As we’ve seen with the previous serialization types, there is always a way to customize the serialization output. For SOAP serialization using the SoapFormatter class, it is the same as for the binary formatter, either the NonSerializable attribute can be applied to class properties or the class to be serialized can implement the ISerializable interface.
To see SoapFormatter in action, take a look at the binary serialization examples (first program example in this chapter). SoapFormatter is illustrated in the example because it is a type of IFormatter and the rules for controlling SOAP serialization are the same as for using the BinaryFormatter. The program examples for this part are given at the beginning of this chapter.
Both the BinaryFormatter and the SoapFormatter demand the SecurityPermissionFlag.SerializationFormatter permission, which is granted only to applications running in the local machine account. Therefore, if an application running either in the intranet or Internet zone attempts to serialize or de-serialize a data stream, an exception will be thrown.
The XmlSerializer does not have any inherent security restrictions, that is, it can be accessed from any zone. The only restriction is if the class being serialized has declarative security attributes, in which case an exception is thrown.