Man lernt NIE aus… oder wie klone ich eine Objektstruktur?



So… gestern war’s soweit. Ich war das erste Mal in meinem Leben auf einem Fußballspiel, genauer bei dem Spiel TSV 1860 vs. Borussia M’gladbach in der Allianz Arena.
Nachdem mich ein Freund darauf hingewiesen hatte mich warm anzuziehen (es hat ein wenig gedauert bis ich realisiert hatte, dass das Stadion offen ist 😉 und in München ist inzwischen der Winter angebrochen) war ich perfekt vorbereitet. Als ich in die U-Bahn stieg trug ich meine Snowboardhose sowie einen warmen Pulli, meine dickste Jacke, eine Mütze über die ich im Notfall noch die Kapuze meiner Jacke ziehen konnte und halbhohe Stiefel über die ich meine Hose ziehen konnte. Schön mollig, echt gemütlich 🙂 Am Stadion angekommen war meine Körpertemperatur auf mehrere hundert Grad angestiegen und ich freute mich endlich in den Kälte zu kommen. Immerhin war ich auf eine Nordpolexpedition vorbereitet.
Sch… war das kalt! Die Temperatur im Stadium war nahe dem absoluten Nullpunkt (in der zweiten Halbzeit fing es außerdem an zu schneien) und hätten wir uns in der Halbzeitpause nicht bewegt wäre ich wahrscheinlich in der Kälte umgekommen. Unglücklicherweise war das Spiel auch so lausig dass es weder die Notwendigkeit gab aufzuspringen und Tore zu bejubeln (das Endergebnis war ein bombiges 0:0) noch eine der Mannschaften anzufeuern. Wäre es nicht soooo kalt gewesen und meine Finger schon tiefgefroren hätte ich an meinem Buch weitergelesen welches ich in weiser Voraussicht eingepackt hatte (Das Ding auf der Schwelle). Tatsächlich war mir zwischenzeitlich so langweilig dass ich es interessanter fand, die Schneeverwirbelungen am Dach der Arena zu beobachten als das Spiel ;-). In diesem Moment wurde mir wieder einmal bewusst dass man nie auslernt. Hätte ich mich doch NOCH dicker angezogen…


Ähnlich geht es mir übrigens mit der Softwareentwicklung deshalb anbei ein kleiner Trick. Eine Frage, die öfter aufkommt ist wie Objektstrukturen geklont werden können. Wer sich in der .NET Klassenbibliothek etwas auskennt dem fällt in diesem Zusammenhang wahrscheinlich die Methode MemberwiseClone ein. Wer jedoch genauer in die Dokumentation schaut wird feststellen, dass MemberwiseClone eine “flache” und keine “tiefe” Kopie eines Objekts erstellt und damit für unser Vorhaben ausfällt.


Als Beispiel soll ein Objekt X dienen, das auf die Objekte A und B verweist. Objekt B wiederum verweist auf ein Objekt C. Eine flache Kopie von X erstellt das neue Objekt X2, das ebenfalls auf die Objekte A und B verweist. Eine tiefe Kopie von X erstellt ein neues Objekt X2, das auf die neuen Objekte A2 und B2 verweist, die Kopien von A und B sind. B2 wiederum verweist auf das neue Objekt C2, das eine Kopie von C ist. Verwenden Sie eine Klasse, die die ICloneable-Schnittstelle implementiert, um eine tiefe oder flache Kopie eines Objekts zu erstellen.


Mit folgendem Trick ist es dennoch einfach eine tiefe Objektstruktur zu klonen. Mit Hilfe eines BinaryFormatter serialisieren Sie eine Objektstruktur in einen MemoryStream und deserialisieren Sie diesen danach in ein neues Objekt. Fertig ist der Klon 🙂    







Imports System.IO


Imports System.Runtime.Serialization.Formatters.Binary


 


Public Class DeepCopy


 


    Public Shared Sub main()


 


        Dim Person1 = New Person With {.Vorname = “Daniel”, .Alter = 31}


 


        Dim Tiere = New List(Of Tier)


        Tiere.Add(New Tier With {.Name = “Fausto”, .Tierart = Tierart.Hund})


        Tiere.Add(New Tier With {.Name = “Lilly”, .Tierart = Tierart.Katze})


 


        Person1.Haustiere = Tiere


 


        Dim Person2 = DeepCloneCopy(Person1)


 


    End Sub


 


    ”’ <summary>


    ”’ Erzeugt eine “deep copy” eines Objekts also eine Kopie des Objekts


    ”’ inclusive aller untergeordneten Objekte.


    ”’ </summary>


    ”’ <param name=”ObjektToClone”>Das zu clonende Objekt.</param>


    ”’ <returns>Eine “deep Copy” des zu clonenden Objekts.</returns>


    ”’ <remarks>Dieser Code funktioniert auch bei rekursiven Objektbeziehungen</remarks>


    Public Shared Function DeepCloneCopy(ByVal ObjektToClone As Object) As Object


 


        Using _memoryStream As New MemoryStream


            Dim _result As Object


 


            Dim _binaryFormatter As New BinaryFormatter


 


            ‘ das Objekt serialisieren


            _binaryFormatter.Serialize(_memoryStream, ObjektToClone)


 


            ‘ An den Anfang des Streams springen


            _memoryStream.Position = 0


 


            ‘ und das Objekt deserialisieren


            _result = _binaryFormatter.Deserialize(_memoryStream)


 


            Return _result


 


        End Using


 


    End Function


 


End Class


 


<Serializable()> _


Public Class Person


 


    Public Vorname As String


    Public Alter As Integer


    Public Haustiere As List(Of Tier)


 


End Class


 


<Serializable()> _


Public Class Tier


 


    Public Name As String


    Public Tierart As Tierart


 


End Class


 


Public Enum Tierart


    Hund


    Katze


End Enum


In diesem Sinne viel Spaß beim Klonen von Objekten und nicht vergessen: Beim Fußball im Winter immer schön warm anziehen 😉


Daniel

Comments (2)

  1. Tim says:

    So ähnlich habe ich es auch in meinem Projekt gemacht nur bei meinem alten Provider, der den Trust-Level auf "Medium" laufen ließ, bekam ich damit Probleme. Ich habe das nicht weiter verfolgt, sondern den Provider gewechselt 🙂