basic serialization question

  • Thread starter Thread starter Bob
  • Start date Start date
B

Bob

Or maybe it's not so basic, I don't know. If I have some serialized object
data, then say I remove one property and add another, is there a way I can
build into the deserialization process a tolerance for such changes? As in,
the deserialilzer fills the fields it can, and ignores the extras?

TIA,
Bob
 
Bob said:
Or maybe it's not so basic, I don't know. If I have some
serialized object data, then say I remove one property
and add another, is there a way I can build into the
deserialization process a tolerance for such changes? As
in, the deserialilzer fills the fields it can, and
ignores the extras?

You could implement ISerializable and catch exceptions on each property
you restore, assigning it a default value there.

Jeremy
 
Jeremy Todd said:
You could implement ISerializable and catch exceptions on each property
you restore, assigning it a default value there.

Jeremy


The documentation doesn't suggest how to do this in the GetObjectData
method. Could you show me?

Bob
 
The documentation doesn't suggest how to do this in the GetObjectData
method. Could you show me?

GetObjectData is where you serialize the object. To deserialize, you
have to create a constructor with the same signature as GetObjectData.
Constructors can't be part of interfaces, so that requirement is kind of
sloppy.

So, something like:

Public Sub New(info As SerializationInfo, context As StreamingContext)

Try
MyStringProperty = info.GetString("MyStringProperty")
Catch ex As Exception
MyStringProperty = "" ' Default value
End Try

Try
MyIntegerProperty = info.GetInt32("MyIntegerProperty")
Catch ex As Exception
MyIntegerProperty = 0 ' Default value
End Try

' Etc.

End Sub

Jeremy
 
I see. I wonder why they can't specify constructors in interfaces...

You wouldn't happen to know if there is a way to directly set each member's
value (from the type's GetMembers) when desierializing? I'm guessing
probably not, which is too bad because that would make this workaround as
complete as using built in serialization/deserialization. The best
generalization I could manage is below, which should suffice for my needs.

Thanks very much for your help,

Bob

Private Sub New(ByVal info As SerializationInfo, ByVal context As
StreamingContext)
For Each f As FieldInfo In Me.GetType.GetFields(BindingFlags.Public
Or BindingFlags.Instance)
Try
f.SetValue(Me, info.GetValue(f.Name, f.FieldType))
Catch ex As Exception
MsgBox(ex.ToString)
End Try
Next
For Each p As PropertyInfo In Me.GetType.GetProperties( _
BindingFlags.Public Or BindingFlags.SetField Or
BindingFlags.Instance)
Try
Dim skip As Boolean
For Each o As Object In
p.GetCustomAttributes(GetType(DesignerSerializationVisibilityAttribute),
True)
If Not DirectCast(o,
DesignerSerializationVisibilityAttribute).Visibility = _
DesignerSerializationVisibility.Visible Then
skip = True
Exit For
End If
Next
If Not skip Then p.SetValue(Me, info.GetValue(p.Name,
p.PropertyType), p.GetIndexParameters)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
Next
End Sub

Private Sub GetObjectData( _
ByVal info As System.Runtime.Serialization.SerializationInfo, _
ByVal context As System.Runtime.Serialization.StreamingContext _
) Implements System.Runtime.Serialization.ISerializable.GetObjectData
For Each f As FieldInfo In Me.GetType.GetFields
If Not f.IsNotSerialized Then
info.AddValue(f.Name, f.GetValue(Me))
End If
Next
For Each p As PropertyInfo In Me.GetType.GetProperties
Dim skip As Boolean
For Each o As Object In
p.GetCustomAttributes(GetType(DesignerSerializationVisibilityAttribute),
True)
If Not DirectCast(o,
DesignerSerializationVisibilityAttribute).Visibility = _
DesignerSerializationVisibility.Visible Then
skip = True
Exit For
End If
Next
If Not skip Then info.AddValue(p.Name, p.GetValue(Me,
p.GetIndexParameters))
Next
End Sub
 
Bob said:
I see. I wonder why they can't specify constructors in interfaces...

Well, under normal circumstances, they don't make a lot of sense. You
can't instantiate an interface, so what good is a constructor? So this is
sort of the exception that proves the rule; it's the kind of thing that only
the Framework itself would use.
You wouldn't happen to know if there is a way to directly set
each member's value (from the type's GetMembers) when
desierializing? I'm guessing probably not, which is too bad because
that would make this workaround as complete as using built in
serialization/deserialization. The best generalization I could manage
is below, which should suffice for my needs.

I don't think there's any automatic way to do this; your way looks
pretty good to me, except for one thing: when serializing, I ignore
properties and only record fields -- after all, in almost all cases
properties are just wrappers for fields to begin with. Using Reflection
(and liberal use of the NonSerialized attribute where appropriate), I bet
you could automate serialization for simple classes fairly easily without
even touching property values. The problem for me comes from delegates --
those can be serialized, but you have to know the context first (normal
events, for instance, normally shouldn't be serialized).

Jeremy
 
Jeremy Todd said:
Well, under normal circumstances, they don't make a lot of sense. You
can't instantiate an interface, so what good is a constructor? So this is
sort of the exception that proves the rule; it's the kind of thing that only
the Framework itself would use.

The compiler already throws an exception when you call a constructor on a
bare interface type, so what harm would there be in allowing constructors in
interfaces? Like a lot of limitations I've come across (especially the
NotInheritable status of some classes), it seems unnecessary.

Bob
 
Back
Top