T
Trev Hunter
Good point. I'll see about modifying the article.
Cheers Jay.
Trev.
Cheers Jay.
Trev.
Jay B. Harlow said:Trev,
I'm not so sure that the NonSerialized attribute needs to be fixed as much
as VB.NET needs to support the Field modifier on attributes. Other wise it
looks like a good article...
In C# you use:[field: NonSerialized]
public event EventHandler NameChanged;
Unfortunately VB.NET only supports Assembly & Module modifiers on attributes
Such as:
<Assembly: NonSerialized>
or
<Module: NonSerialized>
The Field modifier is not supported.
<Field: NonSerialized> causes a syntax error.
Remember the thread from last October?
Hope this helps
Jay
VB.Trev Hunter said:Ok,
I've decided to channel my monkey-rambling energy into providing a
(hopefully) useful article on CodeProject about serialization of VB classes
with events.
Have a look at http://www.codeproject.com/useritems/serializevbclasses.asp
and let me know what you think
Best Regards,
Trev.Atosimple task you may think - stick the <Serialized()> attribute on the class
and away you go. As Homer would say - "D'Oh"
The root of my problem lies in the way VB implements Events and the fact
that you can't apply the <NonSerialized> attribute to the little rascals.
The result of this is that when you serialize ObjectA that has an event
EventX being handled by a method in ObjectB, ObjectB gets serialized right
along with ObjectA.
If you don't believe me, go ahead and try it. Create a serializable class
with an event and some private fields. Create a form an declare an instance
of the class and handle the event (with withevents or addhandler - doesn't
matter). Now try and serialize the instance of the class - you'll get a
serialization exception because the form (not the class you're trying to
serialize) isn't serializable!
Fair enough, you may say. This shouldn't be a big problem - just remove
event handlers before serializing. Why should I have to do this? I can't
even do it reliably (because I have no way of telling who has attachedyoumy
events - it could be some client that I have no control over).
Another problem becomes apparent if you have a custom collection of objects
(say Trigger objects that fire an event periodically). The Collection of
triggers has it's own event which is raised when any of the triggers it
contains fires. A simple (but admittedly probably not the best) way to
implement the collection would be to use addhandler to attach to a trigger's
event when adding it to the collection. Now, guess what happens when
tryand serialize the collection - it works! WooHoo!. Now try and deserialize
it. Again "D'Oh". This time you get an exception because you can't
deserialize a delegate to a private method for security reasons!
In my travels I've had many suggestions about how to get around this and
have come up with some solutions on my own. Here are a few of them and their
pros and cons:
1) Implement ISerializable and don't serialize the events.
Pros: It Works
Cons: Too much work - have to change the GetObjectData method and
Constructor every time I add a field that is to be serialized.
2) Implement an ISerializationSurrogate to strip out the events:
Pros: Dunno
Cons: Pretty complicated to do because the Binary Formatter and Soap
Formatter don't allow you to specify surrogates, so you end up re-writing
them too.
3) Implement ISerializable in a base class and use reflection to get all
private fields in derived classes
Pros: It works
Cons: It's a hack
4) Implement the events in a C# Base class
Pros: You can specify the [NonSerialized] attribute to the event
Cons: Your logic is spread across two projects and two languages.
As you can see. I'm mighty fed up with events. I realize that the fact that
the <NonSerialized> attribute can't be applied to events is probably an
oversight and will probably be fixed in the next version. Saying that, can
anybody think of a valid reason why you would want to serialize an event
(and all objects that handle its events) anyway?
Thanks for putting up with this monkey-ramble. I'm off to learn C#
Cheers,
Trev.