Announcement

Collapse
No announcement yet.

xml Serialisierung von System.Collections.ObjectModel.Collection

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • xml Serialisierung von System.Collections.ObjectModel.Collection

    Hallo liebes Forum,

    ich wette dieses Problem ist bekannt. Ich konnte in der Suche leider nichts finden. Evtl. einfach die falschen Suchbegriffe. Lasse mich gerne auf einen Thread verweisen.

    Zum Thema:
    Wenn ich eine Klasse erstelle, die von System.Collections.ObjectModel.Collection erbt und dieser Klasse dann weitere Eigenschaften hinzufüge, werden diese bei xml serialisierung nicht mit gespeichert. Die eigentliche Klasse in meinem Projekt ist natürlich sehr viel größer. Ich habe aber einmal eine Testklasse geschrieben. Ich hoffe jetzt ist es nicht zu viel Code

    [highlight=vbnet]
    ''' <summary>
    ''' Nur um Fehler beim hinzufügen/ändern der Collection auszugeben
    ''' </summary>
    Public Class EventArgsMessage
    Inherits EventArgs

    Public Sub New(ByVal Message As String)
    Me.Message = Message
    End Sub
    Public Property Message As String
    End Class

    <Serializable()> Public Class TestCollection
    Inherits System.Collections.ObjectModel.Collection(Of String)

    <NonSerialized()> Public Event CollectionError(ByVal sender As Object, ByVal e As EventArgs)

    ''' <summary>
    ''' Das ist besagte Property
    ''' </summary>
    Public Property EineProperty As Integer

    Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As String)
    If String.IsNullOrWhiteSpace(item) Then
    RaiseEvent CollectionError(Me, New EventArgsMessage("String can not be added because it is empty"))
    Else
    MyBase.InsertItem(index, item)
    End If
    End Sub

    Protected Overrides Sub SetItem(ByVal index As Integer, ByVal item As String)
    If String.IsNullOrWhiteSpace(item) Then
    RaiseEvent CollectionError(Me, New EventArgsMessage("String can not be edited because it is empty"))
    Else
    MyBase.SetItem(index, item)
    End If
    End Sub

    Public Sub XMLExport(ByVal ExportFile As System.IO.FileInfo)
    Dim t = Me.GetType
    Dim locXmlWriter = New System.Xml.Serialization.XmlSerializer(t)
    Dim locXmlFile = New System.IO.StreamWriter(ExportFile.FullName)
    Using locXmlFile
    locXmlWriter.Serialize(locXmlFile, Me)
    locXmlFile.Flush()
    locXmlFile.Close()
    End Using
    End Sub

    Public Sub BinExport(ByVal ExportFile As System.IO.FileInfo)
    Dim locFs = New IO.FileStream(ExportFile.FullName, IO.FileMode.Create)
    Dim locContext = New System.Runtime.Serialization.StreamingContext(Syst em.Runtime.Serialization.StreamingContextStates.Fi le)
    Dim locBinaryFormatter = New System.Runtime.Serialization.Formatters.Binary.Bin aryFormatter(Nothing, locContext)
    locBinaryFormatter.Serialize(locFs, Me)
    locFs.Flush()
    locFs.Close()
    End Sub

    Public Shared Function XMLImport(ByVal ImportFile As System.IO.FileInfo) As TestCollection
    Dim locXmlReader = New System.Xml.Serialization.XmlSerializer(GetType(Tes tCollection))
    Dim locXmlFile = New System.IO.StreamReader(ImportFile.FullName)
    Dim locObject As Object
    Using locXmlFile
    locObject = locXmlReader.Deserialize(locXmlFile)
    locXmlFile.Close()
    End Using
    Return DirectCast(locObject, TestCollection)
    End Function

    Public Shared Function BinImport(ByVal ImportFile As System.IO.FileInfo) As TestCollection
    Dim locFs = New System.IO.FileStream(ImportFile.FullName, System.IO.FileMode.Open)
    Dim locContext = New System.Runtime.Serialization.StreamingContext(Syst em.Runtime.Serialization.StreamingContextStates.Fi le)
    Dim locBinaryFormatter = New System.Runtime.Serialization.Formatters.Binary.Bin aryFormatter(Nothing, locContext)
    Dim locObject = locBinaryFormatter.Deserialize(locFs)
    locFs.Close()
    Return DirectCast(locObject, TestCollection)
    End Function
    End Class
    [/highlight]

    Wie man sieht wird in der Klasse verhindert, dass leere Strings hinzugefügt werden. Außerdem sind methoden für die xml als auch für die binäre De/Serialisierung implementiert. Wenn man jetzt folgenden Code in einer Konsolenanwendung laufen lässt...

    [highlight=vbnet]
    Sub Main()
    Dim locCollection = New TestCollection
    AddHandler locCollection.CollectionError, Sub(sender, e)
    Console.WriteLine(DirectCast(e, EventArgsMessage).Message)
    End Sub
    locCollection.Add("Hallo")
    locCollection.Add("Welt")
    locCollection.Add("")
    locCollection.EineProperty = 123

    Dim XmlFile = New System.IO.FileInfo(System.IO.Path.Combine(My.Compu ter.FileSystem.SpecialDirectories.MyDocuments, "TestXml.xml"))
    Dim BinFile = New System.IO.FileInfo(System.IO.Path.Combine(My.Compu ter.FileSystem.SpecialDirectories.MyDocuments, "TestBin.bin"))
    Try
    locCollection.XMLExport(XmlFile)
    locCollection.BinExport(BinFile)
    Catch ex As Exception
    Console.WriteLine(ex.Message)
    End Try

    Dim XmlImport As TestCollection = Nothing
    Dim BinImport As TestCollection = Nothing
    Try
    XmlImport = TestCollection.XMLImport(XmlFile)
    BinImport = TestCollection.BinImport(BinFile)
    Catch ex As Exception
    Console.WriteLine(ex.Message)
    End Try

    If XmlImport IsNot Nothing Then
    Console.WriteLine("XmlImport EineProterty=" & XmlImport.EineProperty.ToString)
    End If
    If BinImport IsNot Nothing Then
    Console.WriteLine("BinImport EineProterty=" & BinImport.EineProperty.ToString)
    End If

    'This program will output:
    'String can not be added because it is empty
    'XmlImport EineProterty = 0
    'BinImport EineProterty = 123

    Console.WriteLine()
    Console.WriteLine("Press key")
    Console.ReadKey()
    End Sub
    [/highlight]

    Wie man sieht wird die Proptery der importierten xml Collection nicht mit gespeichert. Das sieht man auch im xml file. Dort ist nur das ArrayOfString vorhanden. Der Xml-Serialiser speichert also nur die vererbte Item Property der Collection nicht aber die neue Property. Der Binäre Serializer macht alles wunderbar.

    Kann man dieses Problem irgendwie umgehen. Ich kenn mich leider mit XML nicht aus. Muss ich da irgendwelche xml include attribute setzen oder ähnliches

    Ich hoffe ich habe jetzt keinen Thread Müll erstellt. Dieses Problem muss doch schon mal jemand gehabt haben. Wäre für Hilfe echt dankbar. Auch wenn Sie nur ein Link ist.
    Schonmal ein dickes DANKE im vorraus. Freue mich auf Eure Antworten

    Beste Grüße
    Hendrik
    Zuletzt editiert von Caleb; 22.06.2012, 11:28.

  • #2
    Hallo liebes Forum,

    hmmm leider hab ich keine Antworten erhalten.

    Hab ich irgendwas falsch gemacht? Ist die Formulierung unverständlich? Hab ich mich im Ton vergriffen? Funktionieren die Code-Snipets nicht? Ich lass mich gern belehren.

    Würde mich über ein Feedback oder konstruktive Kritik freuen. Ich dachte wirklich, dass dieses Problem bekannt ist...

    Comment


    • #3
      Alles ok mit deiner Frage hat wohl nur keiner eine Antwort oder die Frage übersehen.

      Objekte die IEnumerable/ICollection implementieren, also Listen im allgemeinen, werden vom XmlSerializer besonders behandelt. Läuft weitestgehend daraus hinaus das nur die Objekt der Liste serialisiert werden aber nicht die Liste selbst. Wenn du zusätzliche Properties brauchst und den XmlSerialiser verwenden willst solltest du nicht von Collection ableiten sondern eine Collection/Liste in deiner Klasse kapseln.

      Comment


      • #4
        Hallo Ralf,

        danke für die Antwort. Die Idee mit der Kapselung hatte ich natürlich auch schon. Das Problem ist das die Klasse die ich hier beschrieben habe eine Basisklasse für weitere Klassen ist. Die abgeleiteten Klassen fügen neue Eigenschaften hinzu und überschreiben auch insbesondere die Checkfunktionen ob ein Item hinzugefügt bzw. geändert/gelöscht werden darf oder nicht.

        Lange Rede kurzer Sinn Es ist mir denke ich viel zu viel Arbeit eine Kapselung zu implementieren. Der Rattenschwanz ist mir zu lang. Mittlerweile habe ich mich eh entschieden nur den Binary Serializer zu verwenden.

        Schade, ich hatte gehofft, irgendjemand weiß da ein xml-Attribut oder ähnliches. Aber egal Binär ist auch schön

        Danke nochmal. Falls jemandem noch was einfällt nur her damit. Ich beobachte den Thread mal noch ne Weile...

        Beste Grüße
        Hendrik

        Comment


        • #5
          Schade, ich hatte gehofft, irgendjemand weiß da ein xml-Attribut oder ähnliches. Aber egal Binär ist auch schön
          Ist ein explizit auskodierter Sonderfall im XmlSerializer keine Chance das Verhalten per Attributierung zu ändern. Das Net. Framework hat aber nicht nur einen Xml Serializer. Siehe DataContractSerializer

          Comment

          Working...
          X