2016-03-21 12 views
1

Ich begann vor kurzem mit vb.net von vba zu arbeiten.Serialize Keyedcollection, die eine andere keyedcollection enthält

Für meine geplante Anwendung wollte ich eine KeyedCollection erstellen, die eine andere keyedcollection speichert. Der Grund ist, dass ich eine Art Datenbank habe, in der ich für eine variierende Anzahl von "Parametersätzen" speichern kann, eine jetzt undefinierte Anzahl von "Liste_von_Parametern", wo Koeffizientenarrays gespeichert sind. Mein Problem liegt in der Serialisierung. Wenn ich die XMLSerialization ausführen, werden nur die am tiefsten verschachtelten Elemente korrekt gespeichert. Die Elemente, die eine Ebene darüber liegen, werden nur "Array_of_node" genannt, und alle Variablen außer der keyedcollection werden ignoriert.

Ich hatte erwartet, dass ich statt des Klassennamens sehen würde. Außerdem hatte ich erwartet, so etwas zu sehen.

<Database> 
    <Species> 
    <Name>Parameterset 1</Name> 
    <Node>...</Node> 
    <Node>...</Node> 
    </Species> 

...

Jede Hilfe sehr geschätzt werden würde, Mit freundlichen Grüßen, Johannes.

Dies ist die xml-Ausgabe erhalte ich:

<?xml version="1.0" encoding="utf-8"?> 
<Database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <ArrayOfNode> 
    <Node> 
     <Name>ListOfParameters_1</Name> 
     <value> 
     <double>1</double> 
     <double>2</double> 
     <double>3</double> 
     </value> 
    </Node> 
    <Node> 
     <Name>ListOfParameters_2</Name> 
     <value> 
     <double>5</double> 
     <double>6</double> 
     </value> 
    </Node> 
    </ArrayOfNode> 
    <ArrayOfNode> 
    <Node> 
     <Name>ListOfParameters_1</Name> 
     <value> 
     <double>7</double> 
     <double>8</double> 
     <double>9</double> 
     </value> 
    </Node> 
    <Node> 
     <Name>ListOfParameters_2</Name> 
     <value> 
     <double>10</double> 
     <double>11</double> 
     </value> 
    </Node> 
    </ArrayOfNode> 
</Database> 

Dies ist meine Datenbank:

Imports System.Collections.ObjectModel 
Imports TestListofList 
Imports System.Xml.Serialization 
Imports System.IO 

<Serializable> 
<XmlRootAttribute("Database")> 
Public Class Database 
    Inherits KeyedCollection(Of String, Species) 

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

    Protected Overrides Function GetKeyForItem(item As Species) As String 
     Return item.Name 
    End Function 

    Sub New() 
     MyBase.New() 
    End Sub 

    Sub New(ByVal name As String) 
     Me.New() 
     myName = name 
    End Sub 

    Public Sub SerializeToXML(ByVal filename As String) 
     Dim locXMLWriter As New XmlSerializer(GetType(Database)) 
     Dim locXMLFile As New StreamWriter(filename) 
     locXMLWriter.Serialize(locXMLFile, Me) 
     locXMLFile.Flush() 
     locXMLFile.Close() 
    End Sub 
End Class 

Dies ist die Klasse, die die Liste der "List_of_Coeffiencts" für die verschiedenen Parametersätze speichert:

Imports System.Collections.ObjectModel 
Imports TestListofList 
Imports System.Xml.Serialization 

<Serializable> 
Public Class Species 
    Inherits KeyedCollection(Of String, Node) 

    Public myName As String 


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

    Protected Overrides Function GetKeyForItem(item As Node) As String 
     Return item.Name 
    End Function 

    Sub New() 
     MyBase.New() 
    End Sub 
    Sub New(ByVal Name As String) 
     Me.New() 
     myName = Name 
    End Sub 
End Class 

Und das ist die endgültige "Liste der Koeffizienten"

Public Class Node 
    Private myName As String 
    Private myvalue As Double() 
    Public Property Name() As String 
     Get 
      Return myName 
     End Get 
     Set(ByVal value As String) 
      myName = value 
     End Set 
    End Property 

    Public Property value() As Double() 
     Get 
      Return myvalue 
     End Get 
     Set(ByVal value As Double()) 
      myvalue = value 
     End Set 
    End Property 

    Sub New() 

    End Sub 

    Sub New(ByVal Name As String, value() As Double) 
     myName = Name 
     myvalue = value 
    End Sub 
End Class 

Und das meine Probe Hauptprogramm:

Module Module1 

    Sub Main() 
     Dim dot As Node 
     Dim molecule As Species 
     Dim data As New Database 

     molecule = New Species("Parameterset1") 

     data.Add(molecule) 
     dot = New Node("ListOfParameters_1", New Double() {1, 2, 3}) 
     data.Item("Parameterset1").Add(dot) 
     dot = New Node("ListOfParameters_2", New Double() {5, 6}) 
     data.Item("Parameterset1").Add(dot) 

     molecule = New Species("Parameterset2") 
     data.Add(molecule) 
     dot = New Node("ListOfParameters_1", New Double() {7, 8, 9}) 
     data.Item("Parameterset2").Add(dot) 
     dot = New Node("ListOfParameters_2", New Double() {10, 11}) 
     data.Item("Parameterset2").Add(dot) 




     data.SerializeToXML("C:\test.xml") 
    End Sub 

End Module 
+0

Ihr Problem ist, dass Sie versuchen, Eigenschaften einer Sammlung zu serialisieren. 'XmlSerializer' unterstützt dies nicht. Von [Serialisierung einer Klasse, die die ICollection-Schnittstelle implementiert] (https://msdn.microsoft.com/en-us/library/58a18dwa%28v=vs.110%29.aspx): ** Alle öffentlichen Eigenschaften oder Felder, die hinzugefügt wurden Die Klasse wird nicht serialisiert. **. Siehe [Wie/warum behandelt XmlSerializer eine Klasse anders, wenn sie IList implementiert ?] (Https://stackoverflow.com/questions/31552724) – dbc

+0

Siehe auch [Wenn eine Klasse von List <> geerbt wird, serialisiert XmlSerializer nicht andere Attribute] (https://stackoverflow.com/questions/5069099/when-a-class-is-inherited-from-list-xmlserializer-doesnt-serialize-other-att). Eine Problemumgehung finden Sie beispielsweise in [So wird eine ICollection serialisiert, die auch über Lese-/Schreibeigenschaften nach XML verfügt] (https://stackoverflow.com/questions/34221481/how-to-serialize-an-icollection- that- ebenfalls -has-read-write-properties-to-xml) – dbc

+0

Vielen Dank für Ihre Mühe und Erklärung. Das war mir nicht bewusst. Ich werde den DatacontractSerializer versuchen, der in einem deiner Links erwähnt wird und sehe, dass ich Resultate erhalten kann, die meinem Problem entsprechen. Wenn ja, werde ich posten. – Johannes

Antwort

1

Try this .... (New Code und Klassen)

Imports System.IO 
Imports System.Xml.Serialization 

Module Module1 

Sub Main() 
    Dim Database1 As New List(Of Species) 

    Dim Species1 As New Species 
    Species1.Name = "SpeciesName1" 
    Dim Parameterset1 As New Parameterset 
    Parameterset1.Name = "Parameterset1" 
    Parameterset1.Node.Add("1") 
    Parameterset1.Node.Add("2") 
    Parameterset1.Node.Add("3") 
    Species1.Parameterset.Add(Parameterset1) 

    Database1.Add(Species1) 

    Dim Species2 As New Species 
    Species2.Name = "SpeciesName2" 
    Dim Parameterset2 As New Parameterset 
    Parameterset2.Name = "Parameterset1" 
    Parameterset2.Node.Add("1") 
    Parameterset2.Node.Add("2") 
    Species2.Parameterset.Add(Parameterset2) 

    Database1.Add(Species2) 

    ' to Serialize the object to test.xml 
    Serialize(Database1) 

    ' and to Deserialize from test.xml 
    Dim Database2 As New List(Of Species)(Deserialize()) 
End Sub 

Private Sub Serialize(SpeciesList As List(Of Species)) 

    ' Use a file stream here. 
    Using fs As New StreamWriter("test.xml") 
     ' Construct a XmlSerializer and use it 
     ' to serialize the data to the stream. 
     Dim SerializerObj As New XmlSerializer(GetType(List(Of Species))) 

     Try 
      ' Serialize EmployeeList to the file stream 
      SerializerObj.Serialize(fs, SpeciesList) 
     Catch ex As Exception 
      Console.WriteLine(String.Format("Failed to serialize. Reason: {0}", ex.Message)) 
     End Try 
    End Using 
End Sub 

Private Function Deserialize() As List(Of Species) 
    Dim EmployeeList2 = New List(Of Species)() 

    ' Create a new file stream for reading the XML file 
    Using fs = New StreamReader("test.xml") 
     ' Construct a XmlSerializer and use it 
     ' to serialize the data from the stream. 
     Dim SerializerObj = New XmlSerializer(GetType(List(Of Species))) 

     Try 
      ' Deserialize the hashtable from the file 
      EmployeeList2 = DirectCast(SerializerObj.Deserialize(fs), List(Of Species)) 
     Catch ex As Exception 
      Console.WriteLine(String.Format("Failed to serialize. Reason: {0}", ex.Message)) 
     End Try 
    End Using 
    ' return the Deserialized data. 
    Return EmployeeList2 
End Function 

End Module 

<XmlRoot(ElementName:="Parameterset")> 
Public Class Parameterset 
    <XmlElement(ElementName:="Name")> 
    Public Property Name As String 

    <XmlElement(ElementName:="Node")> 
    Public Property Node As List(Of String) = New List(Of String) 
End Class 

<XmlRoot(ElementName:="Species")> 
Public Class Species 

    <XmlElement(ElementName:="Name")> 
    Public Property Name As String 

    <XmlElement(ElementName:="Parameterset")> 
    Public Property Parameterset As List(Of Parameterset) = New List(Of Parameterset) 
End Class 

<XmlRoot(ElementName:="Database")> 
Public Class Database 

    <XmlElement(ElementName:="Species")> 
    Public Property Species As List(Of Species) = New List(Of Species) 
End Class 

Die XML wie folgt nun aussehen sollte .... .

<?xml version="1.0" encoding="utf-8"?> 
    <ArrayOfSpecies xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
     <Species> 
     <Name>SpeciesName1</Name> 
     <Parameterset> 
      <Name>Parameterset1</Name> 
      <Node>1</Node> 
      <Node>2</Node> 
      <Node>3</Node> 
     </Parameterset> 
     </Species> 
     <Species> 
     <Name>SpeciesName2</Name> 
     <Parameterset> 
      <Name>Parameterset1</Name> 
      <Node>1</Node> 
      <Node>2</Node> 
     </Parameterset> 
     </Species> 
    </ArrayOfSpecies> 
+0

Vielen Dank für Ihre Mühe. – Johannes

+0

Denken Sie, dass es möglich ist, die Datenstruktur in etwas wie das zu ändern? – Johannes

+0

species Parameterset1 Node1 Knoten2 .... Johannes

Verwandte Themen