Copying Object

S

solex

Hello,

I am trying to use serialization to copy objects. The object in question
"Institution" inherits from a parent object "Party" both are marked as
<Serializable()>. Initially I can copy an empty Institution to another
empty Institution, using the following routine:

Private Sub CopyObject(ByRef FromObject As Object, ByRef ToObject As Object)
Dim m As New MemoryStream
Dim b As New BinaryFormatter
b.Serialize(m, FromObject)
m.Position = 0
ToObject = b.Deserialize(m)
End Sub

I then populate some data into the copy and attempt to copy the object back
to the original. When doing so the following error is thrown:

An unhandled exception of type
'System.Runtime.Serialization.SerializationException' occurred in
mscorlib.dll

Additional information: The type myProject.EdtInstitution in Assembly
myProject, Version=1.0.1396.28005, Culture=neutral, PublicKeyToken=null is
not marked as serializable.

The interesting thing is that the object "myProject.EdtInstitution" in the
Assembly myProject is a form and is not being passed into the CopyObject
routine. Any suggestions on how to copy the object back?

Thanks,
Dan
 
J

Jay B. Harlow [MVP - Outlook]

Solex,
Does Party or Institution have custom events that are handled by the Form?

If so, you need to mark the events as NonSerialized.

Unfortunately VB.NET does not support the NonSerialized attribute on events
(VB.NET does not have a Field Attribute Modifier).

The three methods I know of are:
1. Define your events in a C# base class that defines the event as being not
serializable (via [field: NonSerializable] or event procedures).
2. Implement the ISerializable interface and serialize only actual fields.
3. Create a SerializationSurrogate object that only serializes the actual
fields.

For details on the third method see the "Possible Solution to Serializing
Event Handlers in VB" thread from 10 Oct 2003 in the
microsoft.public.dotnet.distributed_apps &
microsoft.public.dotnet.framework.remoting newsgroups.

Details on all three methods can be found in the following three MDSN
Magazine articles on Serialization.
http://msdn.microsoft.com/msdnmag/issues/02/04/net/
http://msdn.microsoft.com/msdnmag/issues/02/07/net/
http://msdn.microsoft.com/msdnmag/issues/02/09/net/

Because I need ISerializable for version control, I'm using the second
method.

Hope this helps
Jay
 
S

solex

Jay,

Yes my classes have events that are handled by the form. Thanks for the
info., I was on my way to implementing the ISerializableSurrogate interface,
but had a question When/How will the SetObjectData get called?

I am copying the object as to mimic a transaction, if the user decides to
cancel any editing I just dispose the copy. If they decide to save I want
to deserialize the copy into the original.

Thanks,
Dan


Jay B. Harlow said:
Solex,
Does Party or Institution have custom events that are handled by the Form?

If so, you need to mark the events as NonSerialized.

Unfortunately VB.NET does not support the NonSerialized attribute on events
(VB.NET does not have a Field Attribute Modifier).

The three methods I know of are:
1. Define your events in a C# base class that defines the event as being not
serializable (via [field: NonSerializable] or event procedures).
2. Implement the ISerializable interface and serialize only actual fields.
3. Create a SerializationSurrogate object that only serializes the actual
fields.

For details on the third method see the "Possible Solution to Serializing
Event Handlers in VB" thread from 10 Oct 2003 in the
microsoft.public.dotnet.distributed_apps &
microsoft.public.dotnet.framework.remoting newsgroups.

Details on all three methods can be found in the following three MDSN
Magazine articles on Serialization.
http://msdn.microsoft.com/msdnmag/issues/02/04/net/
http://msdn.microsoft.com/msdnmag/issues/02/07/net/
http://msdn.microsoft.com/msdnmag/issues/02/09/net/

Because I need ISerializable for version control, I'm using the second
method.

Hope this helps
Jay


solex said:
Hello,

I am trying to use serialization to copy objects. The object in question
"Institution" inherits from a parent object "Party" both are marked as
<Serializable()>. Initially I can copy an empty Institution to another
empty Institution, using the following routine:

Private Sub CopyObject(ByRef FromObject As Object, ByRef ToObject As Object)
Dim m As New MemoryStream
Dim b As New BinaryFormatter
b.Serialize(m, FromObject)
m.Position = 0
ToObject = b.Deserialize(m)
End Sub

I then populate some data into the copy and attempt to copy the object back
to the original. When doing so the following error is thrown:

An unhandled exception of type
'System.Runtime.Serialization.SerializationException' occurred in
mscorlib.dll

Additional information: The type myProject.EdtInstitution in Assembly
myProject, Version=1.0.1396.28005, Culture=neutral, PublicKeyToken=null is
not marked as serializable.

The interesting thing is that the object "myProject.EdtInstitution" in the
Assembly myProject is a form and is not being passed into the CopyObject
routine. Any suggestions on how to copy the object back?

Thanks,
Dan
 
M

Michal Sampson [MSFT]

I think that serialization is not the best means to copy your objects. It
introduces a lot of complexity and a whole new class of bugs that probably
aren't worth it.

What I would suggest is a Clone/Commit model where each object implements a
IClonable (to get the Clone method) and can be called to make an exact
duplicate of itself. You can perform any changes to that object and then
when you are done call Commit (this method isn't on any interface but you
can make one called ICommitable) on the original object passing the clone
and the orginal object will change to match the clone.

Here is a small example:

Interface ICommitable
Inherits IClonable
Sub Commit(ByVal clone as ICommitable)
End Interface

Class Foo
Implements ICommitable
Private name as String
Private someDate as Date

Sub Clone() As Object Implements ICommitable.Clone
Dim clone as New Foo
clone.name = Me.name
clone.someDate = Me.someDate
Return clone
End Sub

Sub Commit(ByVal clone as ICommitable)
Me.name = clone.name
Me.someDate = clone.someDate
End Sub
End Class

If the reason you were using serialization is so you didn't have to
hardcode these values, then you may want to look at reflection to handle
this. This is a more advanced approach that I can go into more detail about
if you would like.

Good luck.
--
Mike Sampson | VB .Net Deployment
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this
message are best directed to the newsgroup/thread from which they
originated.
--------------------
 
S

solex

Michal,

Thanks for your input. I originally had a version of your Clone/Commit
interface in my VB6 project but I was hoping that in my conversion to DotNet
that the framework would be able to transparently handle the mundane tasks
of Getting and Setting the objects data/object references.

I would be interested in some more detail regarding reflection.

Thanks,
Dan
 
J

Jay B. Harlow [MVP - Outlook]

Solex,
When you implement IClone if you can use a shallow cloning you can use
Object.MemberwiseClone.

If you need deep coping (you need to clone objects that are referenced by
this object), then you need to handle the mundane task of getting & setting,
at least for any referenced child objects.

Note: If you implement ISerializable or ISerializableSurrogate, you would
also need to handle the mundane task of getting & setting...

Hope this helps
Jay
 
M

Michal Sampson [MSFT]

I found an article that may be of help to you. It shows an example
implementation of cloning using reflection.

http://www.codeproject.com/csharp/cloneimpl_class.asp

One thing to consider is if this is worth introducing this amount of
complexity into your code. If you only have 4 or so classes that need to be
cloned, it may be worth hardcoding like I suggested earlier. However, if
you have many classes that need cloning or a complex object graph then
reflection based cloning may be for you.

Good luck!

--
Michal Sampson | VB .Net Deployment
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this
message are best directed to the newsgroup/thread from which they
originated.
--------------------
 

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