NonSerialized attribute and events

G

Guest

I am using C# in Visual Studio 2003.
I would like to serialize a class that contains, amongst other things,

public delegate void DocumentsPreferencesChange(object env, Documents e);
public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

However, as it stands, the classes containing any methods/delegates that have been added to OnDocumentsPreferencesChange also have to be serializable: this I do not want.
I do not actually need OnDocumentsPreferencesChange serialized, so would like to be able to use the NonSerializable attribute as follows:

[NonSerializable] public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

Unfortunately, this gives the compile-time error:

'"Attribute 'NonSerialized;' is not valid on this declaration type. It is valid on 'field' declarations only"

I can get round the problem by setting OnDocumentsPreferencesChange to null before serialization and restoring it afterwards, but this seems messy.

Is there a better way?

Any help would be appreciated.
 
B

Bob Powell [MVP]

Serializing classes that have non-serializable members can be a pain. The
best way to overcome the problem is to implement the Memento pattern and
create a serializable object that represents your class without actually
serializing the target class itself.

Just google on "Memento Pattern"

--
Bob Powell [MVP]
Visual C#, System.Drawing

The Image Transition Library wraps up and LED style instrumentation is
available in the June of Well Formed for C# or VB programmers
http://www.bobpowell.net/currentissue.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/gdiplus_faq.htm

The GDI+ FAQ RSS feed: http://www.bobpowell.net/faqfeed.xml
Windows Forms Tips and Tricks RSS: http://www.bobpowell.net/tipstricks.xml
Bob's Blog: http://bobpowelldotnet.blogspot.com/atom.xml






Neil Norfolk said:
I am using C# in Visual Studio 2003.
I would like to serialize a class that contains, amongst other things,

public delegate void DocumentsPreferencesChange(object env, Documents e);
public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

However, as it stands, the classes containing any methods/delegates that
have been added to OnDocumentsPreferencesChange also have to be
serializable: this I do not want.
I do not actually need OnDocumentsPreferencesChange serialized, so would
like to be able to use the NonSerializable attribute as follows:
[NonSerializable] public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

Unfortunately, this gives the compile-time error:

'"Attribute 'NonSerialized;' is not valid on this declaration type. It is
valid on 'field' declarations only"
I can get round the problem by setting OnDocumentsPreferencesChange to
null before serialization and restoring it afterwards, but this seems messy.
 
N

Nicholas Paldino [.NET/C# MVP]

Bob,

I have to disagree with this. You can apply the NonSerializable
attribute to the event, like so:

[field:NonSerializable]
public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

This will prevent the event handlers from being serialized.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Bob Powell said:
Serializing classes that have non-serializable members can be a pain. The
best way to overcome the problem is to implement the Memento pattern and
create a serializable object that represents your class without actually
serializing the target class itself.

Just google on "Memento Pattern"

--
Bob Powell [MVP]
Visual C#, System.Drawing

The Image Transition Library wraps up and LED style instrumentation is
available in the June of Well Formed for C# or VB programmers
http://www.bobpowell.net/currentissue.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/gdiplus_faq.htm

The GDI+ FAQ RSS feed: http://www.bobpowell.net/faqfeed.xml
Windows Forms Tips and Tricks RSS: http://www.bobpowell.net/tipstricks.xml
Bob's Blog: http://bobpowelldotnet.blogspot.com/atom.xml






Neil Norfolk said:
I am using C# in Visual Studio 2003.
I would like to serialize a class that contains, amongst other things,

public delegate void DocumentsPreferencesChange(object env, Documents e);
public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

However, as it stands, the classes containing any methods/delegates that
have been added to OnDocumentsPreferencesChange also have to be
serializable: this I do not want.
I do not actually need OnDocumentsPreferencesChange serialized, so would
like to be able to use the NonSerializable attribute as follows:
[NonSerializable] public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

Unfortunately, this gives the compile-time error:

'"Attribute 'NonSerialized;' is not valid on this declaration type. It
is
valid on 'field' declarations only"
I can get round the problem by setting OnDocumentsPreferencesChange to
null before serialization and restoring it afterwards, but this seems messy.
Is there a better way?

Any help would be appreciated.
 
B

Bob Powell [MVP]

Well, I agree with your disagreement because I just tried it out. However,
your answer, while brilliant, is so esoteric that it took me some time to
find out anything about this attribute target usage. It's certainly not in
MSDN anywhere.

This entry in Rockford Lohtka's blog
http://www.lhotka.net/WeBlog/PermaLink.aspx?guid=776f44e8-aaec-4845-b649-e0d840e6de2c
does explain it and he says "In C# it is possible to use the field: target
on an attribute to tell the compiler to apply the attribute to the backing
field rather than the actual variable. This means we can use [field:
NonSerialized()] to declare an event, which will cause the backing delegate
field to be marked with the NonSerialized attribute. This is a bit of a
hack, but does provide a solution to the problem"

Anyway, Thanks for the education!

--
Bob Powell [MVP]
Visual C#, System.Drawing

The Image Transition Library wraps up and LED style instrumentation is
available in the June edition of Well Formed for C# or VB programmers
http://www.bobpowell.net/currentissue.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/gdiplus_faq.htm

The GDI+ FAQ RSS feed: http://www.bobpowell.net/faqfeed.xml
Windows Forms Tips and Tricks RSS: http://www.bobpowell.net/tipstricks.xml
Bob's Blog: http://bobpowelldotnet.blogspot.com/atom.xml






Nicholas Paldino said:
Bob,

I have to disagree with this. You can apply the NonSerializable
attribute to the event, like so:

[field:NonSerializable]
public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

This will prevent the event handlers from being serialized.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Bob Powell said:
Serializing classes that have non-serializable members can be a pain. The
best way to overcome the problem is to implement the Memento pattern and
create a serializable object that represents your class without actually
serializing the target class itself.

Just google on "Memento Pattern"

--
Bob Powell [MVP]
Visual C#, System.Drawing

The Image Transition Library wraps up and LED style instrumentation is
available in the June of Well Formed for C# or VB programmers
http://www.bobpowell.net/currentissue.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/gdiplus_faq.htm

The GDI+ FAQ RSS feed: http://www.bobpowell.net/faqfeed.xml
Windows Forms Tips and Tricks RSS: http://www.bobpowell.net/tipstricks.xml
Bob's Blog: http://bobpowelldotnet.blogspot.com/atom.xml






Neil Norfolk said:
I am using C# in Visual Studio 2003.
I would like to serialize a class that contains, amongst other things,

public delegate void DocumentsPreferencesChange(object env, Documents e);
public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

However, as it stands, the classes containing any methods/delegates
that
have been added to OnDocumentsPreferencesChange also have to be
serializable: this I do not want.
I do not actually need OnDocumentsPreferencesChange serialized, so
would
like to be able to use the NonSerializable attribute as follows:
[NonSerializable] public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

Unfortunately, this gives the compile-time error:

'"Attribute 'NonSerialized;' is not valid on this declaration type. It
is
valid on 'field' declarations only"
I can get round the problem by setting OnDocumentsPreferencesChange to
null before serialization and restoring it afterwards, but this seems messy.
Is there a better way?

Any help would be appreciated.
 
J

Jim S

I also have a serialization issue and I'm trying to find the best way
to handle it. The Memento pattern may work, but I'm looking for other
suggestions.

My actual application is quite complex so I will simplify the problem
here in its basic form. In a nutshell, I have a tree of objects, each
object is a different node of the tree, like a treeview. All objects
inherit from my INode interface. INode provides a reference to one
parent object and a collection of child nodes (like treeview).

Some of the items in the tree inherit from IDependentObject. This is
an INode which contains a collection of other nodes on which this node
is dependent.

The question is how to do serialization/deserialization. Obviously we
don't want to serialize the references of an IDependentObject. My
current idea is to have a guid associated with each node. In an
IDependentObject, only the guids of the dependent objects would be
serialized/deserialized. Then whenever all deserialization is done,
we'd call a special routine to reconnect references based on the
guids. Please note that I only need serialization/deserialization for
file save/load.

I'm sure that this problem is common and I hope to receive some good
suggestions as to the best practice for solving this.

Thanks in advance.

Jim
 
G

Guest

An interesting and very useful set of answers.
I was attracted to the momento idea as its quite elegant and I have a general like of 'Gang of Four' patterns. However, it means that if the class to be serialized (class Child, say) appears as a member of another serializable class (class Parent, say), then Parent needs to use custom serialization (by implementing ISerializable) so that the momento of the Child can serialized/deserialized rather than the Child itself. Custom serialisation potentially involves a lot of code if Parent has many members that need serialization. However, custom serialization means that version control is easier (if an extra field is added, say, then the custom constructor can take appropriate action when reading a file created using an older version of the class).


The [field:NonSerializable] idea is excellent for the particular problem I had.



Bob Powell said:
Well, I agree with your disagreement because I just tried it out. However,
your answer, while brilliant, is so esoteric that it took me some time to
find out anything about this attribute target usage. It's certainly not in
MSDN anywhere.

This entry in Rockford Lohtka's blog
http://www.lhotka.net/WeBlog/PermaLink.aspx?guid=776f44e8-aaec-4845-b649-e0d840e6de2c
does explain it and he says "In C# it is possible to use the field: target
on an attribute to tell the compiler to apply the attribute to the backing
field rather than the actual variable. This means we can use [field:
NonSerialized()] to declare an event, which will cause the backing delegate
field to be marked with the NonSerialized attribute. This is a bit of a
hack, but does provide a solution to the problem"

Anyway, Thanks for the education!

--
Bob Powell [MVP]
Visual C#, System.Drawing

The Image Transition Library wraps up and LED style instrumentation is
available in the June edition of Well Formed for C# or VB programmers
http://www.bobpowell.net/currentissue.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/gdiplus_faq.htm

The GDI+ FAQ RSS feed: http://www.bobpowell.net/faqfeed.xml
Windows Forms Tips and Tricks RSS: http://www.bobpowell.net/tipstricks.xml
Bob's Blog: http://bobpowelldotnet.blogspot.com/atom.xml






Nicholas Paldino said:
Bob,

I have to disagree with this. You can apply the NonSerializable
attribute to the event, like so:

[field:NonSerializable]
public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

This will prevent the event handlers from being serialized.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Bob Powell said:
Serializing classes that have non-serializable members can be a pain. The
best way to overcome the problem is to implement the Memento pattern and
create a serializable object that represents your class without actually
serializing the target class itself.

Just google on "Memento Pattern"

--
Bob Powell [MVP]
Visual C#, System.Drawing

The Image Transition Library wraps up and LED style instrumentation is
available in the June of Well Formed for C# or VB programmers
http://www.bobpowell.net/currentissue.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/gdiplus_faq.htm

The GDI+ FAQ RSS feed: http://www.bobpowell.net/faqfeed.xml
Windows Forms Tips and Tricks RSS: http://www.bobpowell.net/tipstricks.xml
Bob's Blog: http://bobpowelldotnet.blogspot.com/atom.xml






I am using C# in Visual Studio 2003.
I would like to serialize a class that contains, amongst other things,

public delegate void DocumentsPreferencesChange(object env, Documents e);
public event DocumentsPreferencesChange OnDocumentsPreferencesChange;

However, as it stands, the classes containing any methods/delegates that
have been added to OnDocumentsPreferencesChange also have to be
serializable: this I do not want.
I do not actually need OnDocumentsPreferencesChange serialized, so would
like to be able to use the NonSerializable attribute as follows:

[NonSerializable] public event DocumentsPreferencesChange
OnDocumentsPreferencesChange;

Unfortunately, this gives the compile-time error:

'"Attribute 'NonSerialized;' is not valid on this declaration type. It is
valid on 'field' declarations only"

I can get round the problem by setting OnDocumentsPreferencesChange to
null before serialization and restoring it afterwards, but this seems messy.

Is there a better way?

Any help would be appreciated.
 

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