Serialization

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

Jolinah

Betreff: Serialization

BeitragDi, März 10, 2009 16:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo, ich habe ein bisschen mit der Reflection in BMax rumgespielt und nun ein kleines Modul erstellt welches beliebige Objekte serialisieren kann.

Download:

http://zehr.de/downloads/serialization.zip

Beispiel 1:
Code: [AUSKLAPPEN]
SuperStrict

'Modul einbinden
Import Jolinah.Serialization

'Types zum Testen
Type Person
   Field Adresse:Adresse
   Field Alter:Int
   Field Kinder:Person[]
   Field Eltern:TList
End Type

Type Adresse
   Field Name:String
   Field Strasse:String
   Field PLZ:Int
   Field Ort:String
End Type

Local t:TTypeId = TTypeId.ForName("Person")
For Local m:TMember = EachIn t.EnumFields()
   Print m.Name()
Next

'Testobjekte erstellen
Local p1:Person = New Person
p1.Adresse = New Adresse
p1.Adresse.Name = "Max Muster"
p1.Adresse.Strasse = "Musterstr. 20"
p1.Adresse.PLZ = 54321
p1.Adresse.Ort = "Irgendwo"
p1.Alter = 27
p1.Kinder = New Person[2]
p1.Eltern = New TList

p1.Kinder[0] = New Person
p1.Kinder[0].Alter = 15

p1.Kinder[1] = New Person
p1.Kinder[1].Alter = 24
p1.Kinder[1].Adresse = New Adresse
p1.Kinder[1].Adresse.Name = "Fritz Muster"
p1.Kinder[1].Adresse.Strasse = "Musterstr. 35"
p1.Kinder[1].Adresse.PLZ = 12345
p1.Kinder[1].Adresse.Ort = "Nirgendwo"

Local p2:Person = New Person
p2.Alter = 80

p1.Eltern.AddLast(p2)

p2 = New Person
p2.Alter = 73

p1.Eltern.AddLast(p2)





'Neue Datei test.txt erstellen
Local stream:TStream = WriteFile("test.txt")

'Objekt p1 mit Hilfe des BinarySerializers in die Datei schreiben
Local bs:TSerializer = TBinarySerializer.Create(stream)
bs.SerializeObject("myObject", p1)

'Datei schliessen
stream.Close()




'Datei zum Lesen öffnen
stream = ReadFile("test.txt")

'Objekt mit Hilfe des BinaryDeserializers aus der Datei lesen
Local bds:TDeserializer = TBinaryDeserializer.Create(stream)
Local p3:Person = Person(bds.DeserializeObject())

'Datei wieder schliessen
stream.Close()





'Ausgabe vom neu eingelesenen Objekt
Print p3.Adresse.Name
Print p3.Adresse.Strasse
Print p3.Adresse.PLZ + " " + p3.Adresse.Ort
Print p3.Alter
Print p3.Kinder[0].Alter
Print p3.Kinder[1].Alter
Print p3.Kinder[1].Adresse.Name
Print p3.Kinder[1].Adresse.Strasse
Print p3.Kinder[1].Adresse.PLZ + " " + p3.Kinder[1].Adresse.Ort

For Local p4:Person = EachIn p3.Eltern
   Print p4.Alter
Next

End


Beispiel 2:
Code: [AUSKLAPPEN]
SuperStrict

Import Jolinah.Serialization


Type TLevel
   Field tiles:Int[][]
   
   Method New()
      tiles = New Int[][10]
      For Local i:Int = 0 To 9
         tiles[i] = New Int[10]
      Next
      
      For Local y:Int = 0 To 9
         For Local x:Int = 0 To 9
            tiles[x][y] = Rand(0,50)
         Next
      Next
   End Method
   
   Method Save(filename:String)
      Local stream:TStream = WriteFile(filename)
      Local bs:TBinarySerializer = TBinarySerializer.Create(stream)
      bs.SerializeObject("level", Self)
      stream.Close()
   End Method
   
   Function Load:Object(filename:String)
      Local stream:TStream = ReadFile(filename)
      Local bds:TBinaryDeserializer = TBinaryDeserializer.Create(stream)
      Local level:Object = bds.DeserializeObject()
      stream.Close()
      Return level
   End Function
   
   Method Display()
      For Local y:Int = 0 To 9
         Local s:String = ""
         For Local x:Int = 0 To 9
            s :+ tiles[x][y] + ","
         Next
         Print s
      Next
   End Method
End Type

Print "-----------------------------------------------------------------"
Print "Level (Original):"
Print "-----------------------------------------------------------------"

Local level:TLevel = New TLevel
level.Display()

level.Save("test.txt")

Print "-----------------------------------------------------------------"
Print "Level (Geladen):"
Print "-----------------------------------------------------------------"

Local copy:TLevel = TLevel(TLevel.Load("test.txt"))
copy.Display()




Type TLevelEx Extends TLevel
   Field Name:String = "Level 01-01"
   
   Method Display()
      Print "Levelname: " + Name
      Super.Display()
   End Method
End Type

Local level2:TLevelEx = New TLevelEx

Print "-----------------------------------------------------------------"
Print "LevelEx (Original):"
Print "-----------------------------------------------------------------"

level2.Display()
level2.Save("test.txt")

Print "-----------------------------------------------------------------"
Print "LevelEx (Geladen):"
Print "-----------------------------------------------------------------"

Local copy2:TLevelEx = TLevelEx(TLevel.Load("test.txt"))
copy2.Display()

End



Features:

- Das gleiche Objekt wird nicht 2 mal serialisiert (um Endlosschleifen zu vermeiden, stattdessen wird eine Referenz auf ein bestehendes Objekt eingefügt)

- Es werden alle Zahlentypen, Strings, Arrays und Objekte unterstützt ausser mehrdimensionale Arrays (z.B. Int[,]), da diese per Reflection offenbar nicht richtig ausgelesen werden können. Verschachtelte Arrays (z.B. Int[][]) funktionieren aber.

- Felder von Types werden mit Namen und Wert gespeichert, so dass ein Type nachträglich geändert werden kann und beim Deserialisieren trotzdem noch die richtigen Felder gefüllt werden.

Negatives / Bugs:

- Da die Feldnamen mitgespeichert werden gibt es ja nach Anwendung ziemlich viel Redundanz.

- Dadurch ist das Modul nicht unbedingt geeignet um Objekte per Netzwerk zu übertragen.

- Bugs sind nicht auszuschliessen Wink Die wichtigsten Fälle habe ich getestet, aber je nach Verschachtelung der Types etc. könnte es evtl. noch zu Fehlern kommen.


Wie gesagt ist das eher eine Spielerei, aber vielleicht kanns ja jemand brauchen...

DAK

BeitragDi, März 10, 2009 19:23
Antworten mit Zitat
Benutzer-Profile anzeigen
hey, du hast den ersten teil von dem gemacht, wo ich seit längerem nebenbei am schrauben bin...

ich wollt aus dem ganzen n netzwerk-modul machen... wenn ich wieder zeit hab (und nix besseres zu tun) mach ich (falls du einverstanden bist) aus dem Modul n netzwerkmodul. muss mas hald noch bissal auf netzwerk optimieren, aber als basis sollt sich deins auf jeden verwenden lassen.
Gewinner der 6. und der 68. BlitzCodeCompo

Jolinah

BeitragDi, März 10, 2009 20:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi, klar, kannst du abändern wie du magst Wink Ich hoffe du findest dich im Code zurecht, hab ihn leider nicht so gut kommentiert...

An Netzwerk-Übertragung hatte ich auch schon gedacht, dafür müsste man wahrscheinlich einfach die Eigenschaften-Namen weglassen und noch ein paar weitere Optimierungen machen. Einziger Nachteil wenn man das dann als Netzwerkprotokoll nutzen würde: Wenn zwei Clients unterschiedliche Versionen haben kann das zu Problemen führen...

DAK

BeitragMi, März 11, 2009 13:16
Antworten mit Zitat
Benutzer-Profile anzeigen
joa... was ma noch machen könnt wär schaun, in welchem objekt sich was geändert hat und nur die änderungen schicken...

würd hald mehr speicher kosten...

das mit den unterschiedlichen versionen... ja... muss ma hald updaten Wink
Gewinner der 6. und der 68. BlitzCodeCompo

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group