5

I'v build a NotInheritable Serilizer that serilizes all my classes and list of classes with success. Until I'v build a list of class that contains a list of classes. I'm getting the runtime Exeption: There was an error generating the XML document. resulting in a perfectly empty XML :(

These are my classes to serilize:

<System.Serializable> _
<System.Xml.Serialization.XmlInclude(GetType(StatisticItem))> _
Public Class Statistic
    Public StatItem As New list(Of StatisticItem)
    'Bla bla bla
end class


<Serializable> _
Public Class StatisticItem              
        Private stStatPath As String = ""    
        Private eStatType As StatType = 0
        Private iBatchNumber As Int32 = 0
end class

And the serializer:

Public NotInheritable Class XmlSerializer       

    Public Shared Sub Serialize(Of T)(ByVal obj As T, sConfigFilePath As String)        
        Dim XmlBuddy As New System.Xml.Serialization.XmlSerializer(GetType(T))
        Dim MySettings As New System.Xml.XmlWriterSettings()
        MySettings.Indent = True
        MySettings.CloseOutput = True       
        Dim MyWriter As System.Xml.XmlWriter=System.Xml.XmlWriter.Create(sConfigFilePath,MySettings)        
        XmlBuddy.Serialize(MyWriter,obj) 
        MyWriter.Flush()
        MyWriter.Close()    

        ' ----- OLD CODE FOR SERIALIZE, NEXTLINE IN XML DOESNT WORK ON WIN CE -------, 
        ' B.T.W. Using This code to serilize gives the exact same fault             
        'Dim XmlBuddy As New System.Xml.Serialization.XmlSerializer(GetType(T))
        'Dim objStreamWriter As New StreamWriter(sConfigFilePath)
        'XmlBuddy.Serialize(objStreamWriter, obj)
        'objStreamWriter.Close()
    End Sub
 end class

And this is the call:

 XmlSerializer.Serialize(Of list(Of Statistic))(StatCollection, CommCtrl.PathStatisticFile)

If i comment the list in StatisticItem everything works.

I think if I Implement IXmlSerializable in StatisticItem I can tell the serializer how to work to make it work, but I see other code example on the internet where this works without all this effort and I prefer a clean solution, that is about the same as all my other classes.

Hope one of you guys can help me out

Rob Heijligers
  • 193
  • 1
  • 2
  • 9
  • Rob, that wouldn't make your code un-clean. Adding what you need isn't unneccessary. Can you add it, test it, and let us know if it worked. No sense in fixing what isn't broken. –  Aug 08 '14 at 13:46
  • I was just working on it, but now I notice that I have to write the code to write all the names and values of Statisic and statistic items. and of course the code to read everything afterwards. I know there must be an easier way to serialize this. I made the serializer like this so it would recognize the type of object it receives. Damm it you late night Bbq – Rob Heijligers Aug 08 '14 at 14:00
  • The serialisers will only serialise `Public` properties (with your code as it is). Can't you change the `Private`s to `Public`s?? – Grim Aug 08 '14 at 18:03
  • I have tried that, I didn't include the public properties in the code. I'm still trying some things now I have a fresh look, If I can't fix in this morning I will have to type everything out manually with the IXmlSerializable include.. Too bad if there is anyone with good tips, any help is useful. – Rob Heijligers Aug 11 '14 at 08:12

2 Answers2

2

Yes solved!, To be honest I changed so much small things that I still don't know what the cause was. Maybe that there were still some private members. Anyway, maybe the code can be useful for anyone:

Public Class Statistic 

    'Properties         
    Private eStatName As String                     
    Private eStatSort As StatSort            
    Private StatItem As New list(Of StatisticItem)


    Public Property Name() As String
      Get
          Return eStatName
      End Get
      Set(ByVal value As String)
          eStatName = value
      End Set
    End Property

    'Other public properties
End class



Public Class StatisticItem  
    Private stStatPath As String = ""    
    Private eStatType As StatType = 0
    Private iBatchNumber As Int32 = 0

Public Property Path() As String
    Get
        Return stStatPath
    End Get
    Set(ByVal Value As String)
        stStatPath = Value
    End Set
End Property

' The other Public Properties

Serializer:

Public NotInheritable Class XmlSerializer

    ''' <summary>
    ''' Convert a class state into XML
    ''' </summary>
    ''' <typeparam name="T">The type of object</typeparam>
    ''' <param name="obj">The object to serilize</param>
    ''' <param name="sConfigFilePath">The path to the XML</param>
    Public Shared Sub Serialize(Of T)(ByVal obj As T, sConfigFilePath As String)        
        Dim XmlBuddy As New System.Xml.Serialization.XmlSerializer(GetType(T))
        Dim MySettings As New System.Xml.XmlWriterSettings()
        MySettings.Indent = True
        MySettings.CloseOutput = True       
        Dim MyWriter As System.Xml.XmlWriter = System.Xml.XmlWriter.Create(sConfigFilePath,MySettings)      
        XmlBuddy.Serialize(MyWriter,obj) 
        MyWriter.Flush()
        MyWriter.Close()    
    End Sub



''' <summary>
''' Restore a class state from XML
''' </summary>
''' <typeparam name="T">The type of object</typeparam>
''' <param name="xml">the path to the XML</param>
''' <returns>The object to return</returns>
Public Shared Function Deserialize(Of T)(ByVal xml As String) As T      
    Dim XmlBuddy As New System.Xml.Serialization.XmlSerializer(GetType(T))
    Dim fs As New FileStream(xml, FileMode.Open)
    Dim reader As New Xml.XmlTextReader(fs) 
    If XmlBuddy.CanDeserialize(reader) Then
        Dim tempObject As Object = DirectCast(XmlBuddy.Deserialize(reader), T)         
        reader.Close()
        Return tempObject
    Else
        Return Nothing
    End If
End Function
end class

The call of the Serializer:

Try                     
     XmlSerializer.Serialize(Of list(Of Statistic))(StatCollection, CommCtrl.PathStatisticFile)
Catch ex As Exception
     msgbox(ex.Message)
End Try

The call of the deSerializer:

Try
     StatCollection = XmlSerializer.Deserialize(Of list(Of Statistic)(CommCtrl.PathStatisticFile)
Catch ex As Exception
     msgbox(ex.Message)
end Try
Hadi
  • 36,233
  • 13
  • 65
  • 124
Rob Heijligers
  • 193
  • 1
  • 2
  • 9
0

I needed to do this also but create a string instead. Here's my solution:

    Public Shared Function Serialize(Of T)(ByVal obj As T) As String
        Dim xml As New System.Xml.Serialization.XmlSerializer(GetType(T))
        Dim ns As New System.Xml.Serialization.XmlSerializerNamespaces()
        ns.Add("", "") 'No namespaces needed.
        Dim sw As New IO.StringWriter()
        xml.Serialize(sw, obj, ns)

        If sw IsNot Nothing Then
            Return sw.ToString()
        Else
            Return ""
        End If
    End Function


    Public Shared Function Deserialize(Of T)(ByVal serializedXml As String) As T
        Dim xml As New System.Xml.Serialization.XmlSerializer(GetType(T))
        Dim sr As New IO.StringReader(serializedXml)
        Dim obj As T = CType(xml.Deserialize(sr), T)

        Return obj
    End Function
jrjensen
  • 191
  • 9