Autore Topic: Codice per la serializzazione degli oggetti  (Letto 313 volte)

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.724
  • Ne mors quidem nos iunget
    • Mostra profilo
Codice per la serializzazione degli oggetti
« il: 22 Febbraio 2013, 22:42:48 »
Vorrei riportare un messaggio inviato dall'utente Jussi Lahtinen della M.L.I, il quale ha messo a disposizione un codice, da lui scritto, per la serializzazione degli oggetti:


« This is my implementation for object serialization, it's still bit
incomplete, but it's already usable.
And I thought some of you might find it very useful. I use it now to save
objects to file.

Right now it can handle objects with native datatypes (if you use it
recursively it can be made to handle all types).

What do you think? Is there better way to do this?
Maybe with Object.Address() & Object.SizeOf() ?

Example of how to use it:

'This will save the object to file.

Dim MyObject As MyClass
Dim hFile As File

hFile = Open "~/Desktop/testtest" For Create
SaveValues(hFile, MyObject)
Close #hFile


'This will load the object from file.

hFile = Open "~/Desktop/testtest" For Read
LoadValues(hFile, MyObject)
Close #hFile


And the code itself:

Public Function SaveValues(hStream As Stream, hObject As Object)

Dim hCls As Class = Object.Class(hObject)
Dim sTmp As String

For Each sTmp In hCls.Symbols.Sort(gb.Binary)
  If hCls[sTmp].Kind = Class.Variable Then

    Select Case hCls[sTmp].Type

    Case "h" 'short
      Write #hStream, Object.GetProperty(hObject, sTmp) As Short

    Case "b" 'boolean
      Write #hStream, Object.GetProperty(hObject, sTmp) As Boolean

    Case "c" 'byte
      Write #hStream, Object.GetProperty(hObject, sTmp) As Byte

    Case "i" 'integer
      Write #hStream, Object.GetProperty(hObject, sTmp) As Integer

    Case "l" 'long
      Write #hStream, Object.GetProperty(hObject, sTmp) As Long

    Case "s"
      Write #hStream, Object.GetProperty(hObject, sTmp) As String

    Case Else
      Error.Raise("Error! Missing variable type definition.")
    End Select

  Endif
Next

End

Public Function LoadValues(hStream As Stream, hObject As Object)

Dim hCls As Class = Object.Class(hObject)
Dim sTmp As String

Dim h As Short
Dim b As Boolean
Dim c As Byte
Dim i As Integer
Dim l As Long
Dim s As String

For Each sTmp In hCls.Symbols.Sort(gb.Binary)
  If hCls[sTmp].Kind = Class.Variable Then

    Select Case hCls[sTmp].Type

    Case "h" 'short
      h = Read #hStream As Short
      Object.SetProperty(hObject, sTmp, h)

    Case "b" 'boolean
      b = Read #hStream As Boolean
      Object.SetProperty(hObject, sTmp, b)

    Case "c" 'byte
      c = Read #hStream As Byte
      Object.SetProperty(hObject, sTmp, c)

    Case "i" 'integer
      i = Read #hStream As Integer
      Object.SetProperty(hObject, sTmp, i)

    Case "l" 'long
      l = Read #hStream As Long
      Object.SetProperty(hObject, sTmp, l)

    Case "s"
      s = Read #hStream As String
      Object.SetProperty(hObject, sTmp, s)

    Case Else
      Error.Raise("Error! Missing variable type definition.")
    End Select

  Endif
Next

End


Jussi
»
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.724
  • Ne mors quidem nos iunget
    • Mostra profilo
Re: Codice per la serializzazione degli oggetti
« Risposta #1 il: 23 Febbraio 2013, 12:58:06 »
« If it hits an object property then set a marker in the file and call
itself on that object. There is only one problem with this: your code can
only handle (public) properties. Actually an object serialised by your code
and then deserialised could stop working properly because Private variables
not bound to properties (which weren't saved therefore) may not contain the
right values anymore.


> What do you think? Is there better way to do this?
> Maybe with Object.Address() & Object.SizeOf() ?


I think you can use these to generate a binary dump of an object to a file,
but the thing is: the backing structures you dump most likely contain
pointers to other structures (Gambas objects or structures allocated by a
shared library!) which will become invalid pointers when loaded into another
process.

I think the solution to both above problems is already in Settings.Write().
It is capable of _correctly_ writing and restoring objects if they export a
Settings property. As a matter of fact, the object itself only really knows
what must be serialised and can also provide its private variables.

Alas, I don't see how the serialisation process could be done _without_ the
object being deeply involved by providing its internal information.

Regards,
Tobi
»


« >If it hits an object property then set a marker in the file and call
> itself on that object. There is only one problem with this: your code can
> only handle (public) properties. Actually an object serialised by your code
> and then deserialised could stop working properly because Private variables
> not bound to properties (which weren't saved therefore) may not contain the
> right values anymore.
>


You are right.
I didn't think about that, because I wrote this piece of code couple
specific classes in my mind.
So, it's not universal solution.



> I think you can use these to generate a binary dump of an object to a file,
> but the thing is: the backing structures you dump most likely contain
> pointers to other structures (Gambas objects or structures allocated by a
> shared library!) which will become invalid pointers when loaded into
> another
> process.
>


True, that is troublesome to overcome.


> I think the solution to both above problems is already in Settings.Write().
> It is capable of _correctly_ writing and restoring objects if they export a
> Settings property.


Settings property is just pretty limited with it's capabilities when
speaking of serialization,
but of course it's very good for it's intended use.



> As a matter of fact, the object itself only really knows
> what must be serialised and can also provide its private variables.
>
> Alas, I don't see how the serialisation process could be done _without_ the
> object being deeply involved by providing its internal information.


I understand your point.
I think the object should be designed to be serialized, or you have to do
it manually.

Now I wonder how Boost library does serialization!


Jussi
»
« Ultima modifica: 23 Febbraio 2013, 23:13:04 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »