Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Serializable Generic Collection

3.00/5 (6 votes)
27 Nov 2007CPOL 1   219  
A Generic collection that can be serialized in XML format.

Introduction

By default, Generic Collections can not be serialized using an XML serializer. I am trying to create a generic collection that can be serialized in XML format.

VB
Public Class CollectionBase(Of T)
        Inherits System.Collections.ObjectModel.Collection(Of T)
        Implements System.Xml.Serialization.IXmlSerializable

About this Collection

When we implement an XmlSerializable object, we must inherit it from IXmlSerializable. And then, we must implement three methods: GetSchema, ReadXml, WriteXml. In GetSchema, we must return a string that contains the XML schema about the object (we leave it blank in this version!). The ReadXml method will contain statements that deserialize the XML to objects, and finally in WriteXml, we serialize our collection into XML.

VB
Public Sub ReadXml(ByVal reader As System.Xml.XmlReader) _
           Implements System.Xml.Serialization.IXmlSerializable.ReadXml
    Dim pc() As PropertyInfo = GetType(T).GetProperties()
    While reader.Read()
        If reader.Name = GetType(T).Name Then
            reader.Read()
            If pc.Length > 0 Then
                Dim ti As T = GetInstance()
                For i As Int32 = 0 To pc.Length - 1
                    If pc(i).CanRead And pc(i).CanWrite Then
                        Dim st As SerilalizeType = GetSerilalizeType(pc(i).PropertyType)
                        If st = SerilalizeType.Complex Then
                            Dim o As Object = GetInstance(pc(i).PropertyType)
                            DesrializeObject(reader, o, pc(i).Name)
                            pc(i).SetValue(ti, _
                                           Convert.ChangeType(o, pc(i).PropertyType), _
                                               Nothing)
                        ElseIf st = SerilalizeType.Guid Then
                            Dim strGuid As String = reader.ReadElementString(pc(i).Name)
                            Dim newId As Guid = New Guid(strGuid)
                            pc(i).SetValue(ti, New Guid(strGuid), Nothing)

                        ElseIf st = SerilalizeType.Array Then
    
                            Dim o As Object = Nothing
                            DesrializeArray(reader, o, pc(i).PropertyType)
                            pc(i).SetValue(ti, _
                                    Convert.ChangeType(o, pc(i).PropertyType), _
                                    Nothing)

                        ElseIf st = SerilalizeType.ICollection Then
                            Dim o As Object = Nothing
                            DesrializeCollection(reader, o, pc(i).PropertyType)
                            pc(i).SetValue(ti, _
                                   Convert.ChangeType(o, pc(i).PropertyType), _
                                       Nothing)
                        Else
                            pc(i).SetValue(ti, _
                            Convert.ChangeType( _
                            reader.ReadElementString(pc(i).Name), pc(i).PropertyType), _
                                Nothing)
                        End If
                    End If
                Next
                Me.Add(ti)
            End If
        End If
    End While
End Sub

Public Sub WriteXml(ByVal writer As System.Xml.XmlWriter) _
        Implements System.Xml.Serialization.IXmlSerializable.WriteXml
    Dim pc() As PropertyInfo = GetType(T).GetProperties()
    Dim ti As T = Nothing
    For i As Int32 = 0 To Me.Items.Count - 1
        ti = Me.Item(i)
        writer.WriteStartElement(GetType(T).Name)
        For j As Int32 = 0 To pc.Length - 1
            If pc(j).CanRead And pc(j).CanWrite Then
                writer.WriteStartElement(pc(j).Name)
                Dim st As SerilalizeType = GetSerilalizeType(pc(j).PropertyType)
                If st = SerilalizeType.Complex Or _
                   st = SerilalizeType.Array Or _
                   st = SerilalizeType.ICollection Then
                    writer.WriteRaw(SerializeObject(pc(j).GetValue(ti, Nothing)))
                Else
                    writer.WriteString(pc(j).GetValue(ti, Nothing).ToString())
                End If
                writer.WriteEndElement()
            End If
        Next
        writer.WriteEndElement()
    Next
End Sub

Using the Code

As is usual, here is how we use Generic Collections:

VB
Dim MyCol As New DNE.Components.CollectionBase(Of SomeObject)

I suggest inheriting your collection from this class. Our collection can now deserialize simple properties like string, integer, and arrays and objects that inherits from ICollection.

ToDo

Support serialization for Hashtables, Enums, and ....

History

  • Version 0.2: Support for Array and ICollection, fixed some bugs. 28/11/2007.
  • Version 0.1: Initial release. 11/11/2007.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)