Serialization Gurus? Unexpected Binary Behavior

G

google

I'm seeing something very odd with binary serialization, and I wanted
to make sure I'm not misunderstanding what goes on under the hood.

Let's say you have a graph with two objects, one referencing the other
(parent/child):
A -> B
Now you have a totally separate but identical graph with an A' and B':
A' -> B'
Property-by-property these objects have the same primitive values.
They're clones, essentially. And let's say there's a grandparent X.
X -> A' -> B'

What I *think* I'm seeing is that the bytes coming out of binary
serialization with an input of A are different than those coming from
binary serialization with an input of A'. The only thing I can seem to
point at as a cause is the sheer existence of X, even though A' has no
direct knowledge of X.

If this is the case, it definitely breaks everything I thought I knew
about binary serialization. I'm actually hoping that I'm totally wrong
here, but after spending about 8 hrs digging deeply into the issue,
this is the only straw left to grasp at.

My specific issue is of course much more complicated. My A->B graph
has more items, with some circular references between them. There are
some structs. Maybe even some Equals overrides (which I know get used
by XML serialization). I've taken a fine toothed comb to this using
the "Make Object ID" functionality of the Watch window... And for the
life of me I can't locate any difference between "the graph starting
from A" and "the graph starting from A' "... But yet the binary
serializations of each, when compared byte-by-byte, are different. One
is always exactly 183 bytes longer. Any ideas would be greatly
appreciated.

This is .NET 2.0, C#.

Thanks,

James
 
T

tommaso.gastaldi

Hi James,

in my opinion, while it is often useful to have *at runtime* cross
reference, you do not need usually to serialize both. Usually you have
a cross reference between 2 object where one act like a kind of
"parent" (or "container") and the lther like a child:

class Parent
Public Child as Child
....
end class

class Child
<nonserialized()> Public Parent
....

function RestoreChild(Parent as Parent)
me.Parent = Parent
end function

end class

when you "restore" (possible Deserializations+Relinks) the child you
would also relink, at runtime, the Parent, which usually is restored
(possible Deserializations+Relinks) before the child. Sometimes for the
restore it is necessary to backup some info will will allow to relink
the objects.

I would also suggest to define an interface, say
"IObjectWithBackupRestore" to automatize the backup/restored of the
objects (can be both key or Values) stored within hashtables,
SortedList, etc. Think for instance to the case, common in real world
application, where the Comparer used for a SortedList depends on
members which need to be relinked or restored, before being able to use
the restored (deserialized) SortedList (or else you would get null
pointers)...

Actually for complex application one has to implement a whole engine
and strategies to deal effectively with this issue (restoring the
runtime environment), that in my opinion is one that requires time and
insight for a programmer to get right in all its nuances. It is even
possible that people who never build really complex applications are
not really aware of the whole problem ,,,

-tom



This is an extreme simplification, but the principle is applicable in
several occasion.


(e-mail address removed) ha scritto:
 
G

google

Tom,

Thanks for the response. We actually aren't serializing for the
purpose of storage (or data transmission), at least not yet. But when
we do, your recommendations will come in handy. We are currently
serializing only as a way to compare two object graphs in a "by value"
sense. Unfortunately, it looks like binary serialization isn't cut out
for this purpose.

James
 
T

tommaso.gastaldi

Hi James,

I am not clear what you are actually doing, but it sounds that, if it's
not a job for Icomparable, Icomparer ... , then it is probably
something for "System.Reflection". Perhaps something on the lines of:
(altought I can't see for the moment how this could be useful)

Assume a form with 1 button. This compares 2 instances of an object.
Returns: FALSE, TRUE. Just the general idea, must be refined...

'---------------------------

Imports System.Reflection

Class MyObj
Public R As New System.Text.StringBuilder
Public V As String = "Tom"
End Class


Public Class Form1
Inherits System.Windows.Forms.Form


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click

Dim MyObj1 As New MyObj
Dim MyObj2 As New MyObj
MsgBox(CompareObjs(MyObj1, MyObj2))

MyObj1.R = MyObj2.R
MsgBox(CompareObjs(MyObj1, MyObj2))

End Sub

Function CompareObjs(ByVal Obj1 As Object, ByVal Obj2 As Object) As
Boolean

'Fields
Dim FieldInfos As FieldInfo() =
Obj1.GetType.GetFields((BindingFlags.Static Or _

BindingFlags.Instance Or _

BindingFlags.NonPublic Or _

BindingFlags.Public))
For Each FieldInfo As FieldInfo In FieldInfos
With FieldInfo
If IsReference(FieldInfo.GetValue(Obj2)) Then
Dim V1 As Object = FieldInfo.GetValue(Obj1)
Dim V2 As Object = FieldInfo.GetValue(Obj2)
If Not Object.ReferenceEquals(V1, V2) Then Return
False
Else
If Not Object.Equals(FieldInfo.GetValue(Obj1),
FieldInfo.GetValue(Obj2)) Then Return False
End If
End With
Next FieldInfo

'Properties
Dim PropertyInfos As PropertyInfo() =
Obj1.GetType.GetProperties
For Each PropertyInfo As PropertyInfo In PropertyInfos
With PropertyInfo
'...
End With
Next PropertyInfo

'...

Return True

End Function

End Class


'---------------------------

in case don't be afraid to email me... sounds like you are doing
something interesting ... ;-)

Enjoy

-tom


(e-mail address removed) ha scritto:
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top