< Another C# XML Serialization Program Example | Main | Chap 5: Uniform Resource Identifiers >

 


 

Chapter 4 Part 15:

Serialization

 

 

What do we have in this chapter 4 Part 15?

  1. Another VB .NET XML Serialization Program Example

  2. SOAP Serialization

  3. Code Access Security

 

 

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.

 

Another VB .NET XML Serialization Program Example - creating a new class library project

 

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.

 

Another VB .NET XML Serialization Program Example - changing the DLL typr to EXE type application and setting up the Main() subroutine as the startup  

 

Build and run the project. The following are sample outputs.

 

Another VB .NET XML Serialization Program Example - a sample output with default argument values

 

Another VB .NET XML Serialization Program Example - running the program from command line with serialize and simple options

 

Another VB .NET XML Serialization Program Example - running the program from command line with serialize and attribute options

 

The generated XML file, simplexmlfile.xml as seen through browser is shown below.

 

Another VB .NET XML Serialization Program Example - the generated XML file used for serialization and de-serialization opened in the Internet Browser

 

SOAP Serialization

 

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.

 

Code Access Security

 

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 deserialize 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.

 

 

 


 

< Another C# XML Serialization Program Example | Main | Chap 5: Uniform Resource Identifiers >