|
Introduction
Because of the way VB.NET implements events, when you serialize an
object, its events get serialized too (because events are actually
implemented using hidden multicast delegate fields). A side effect of
this is that any object which handles events raised by the object being
serialized will be considered part of the object graph and will be
serialized too.
This can result in the following undesirable situations:
- You end up serializing objects that you didn't expect, resulting in a
larger stream.
- If the object handling the events is not
Serializable, then
the serialization process will throw an exception.
There are many different ways to get around this problem, but this is the
solution that I've found easiest to implement and which requires the least
work when using in practice.
Background
I originally came across this problem while trying to serialize objects
written in VB.NET for sending across the remoting infrastructure, but the
problem applies to serializing objects in general. The root of the problem
is the fact that you cannot apply the <NonSerialized> attribute to events in VB (you can
in C# by using the Field: modifier). As a result, there
is no simple way of telling the runtime not to serialize the event fields.
Note: I'm not 100% sure, but I think the next version of VB.NET
will allow this, so you won't need this workaround then.
As a better explanation, consider the following sample code:
Public Sub Main
Dim objHandler As New ObjectThatCatchesEvents
Serializable
Dim objRaiser As New ObjectThatRaisesEvents
AddHandler objRaiser.NameChanged, AddressOf objHandler.NameChangedHandler
Dim objStream As New MemoryStream
Dim objFormatter As New Formatters.Binary.BinaryFormatter
objFormatter.Serialize(objStream, objRaiser)
End Sub
A serialization exception will be raised because objHandler
is of a type that is not Serializable - even though we're
trying to serialize objRaiser, not objHandler.
There are a number of ways to get around this problem. Here are a few of
them:
- Remove all event handlers before serialization:
This will work, but how can you be sure you have removed all the event
handlers? What if you are writing a class library and don't have any control
over how clients handle your events? You could access the hidden event
delegate (use MyEventEvent.GetInvocationList() where
MyEvent is the name of your event) and remove all handlers
there, but it can get tedious if you have a lot of events-especially if you
want to reattach the handlers after the serialization process has
finished.
- Implement ISerializable:
You could implement ISerializable in your class and
manually determine what information is to be serialized and leave out
the event fields. I've found this to be slightly tedious as you have to
implement the GetObjectData method and the special
constructor in your class (and all derived classes). You also have to
remember to add code to these methods to serialize and deserialize all
fields - especially when you add or remove a field.
- Implement a Serialization Surrogate:
This method effectively takes over from implementing
ISerializable in your class. You could implement a generic
Surrogate and use it to filter out event delegates from all objects being
serialized. The problem with this approach is that it's practically
impossible to use with the serialization process in the Remoting
infrastructure as the built-in binary and SOAP formatters don't allow you to
specify surrogates in Remoting - you'd end up having to write your own
formatter like Peter Himschoot did (http://users.pandora.be/Peter.Himschoot/).
- Implement your events in a separate class that is not serialized:
You could separate your events into a small object and expose them to
clients through a field and mark the field as <NonSerialized>. I don't particularly like this idea
because it separates your code functionality across two separate
classes.
- Implement your events in a C# base class:
Again, you pay the price of your functionality being split across two
classes (even worse this time, because it's in a different language!)
- Drop VB and use C# ;-)
Not an easy task for VB monkeys like myself!
- Wait for VB.NET to support the Field: modifier for attributes
I don't have the patience!
- Stop using events:
No way, they're too handy. Besides, aren't events useful in an event
driven architecture?
My Solution
The solution that I've come up with is a variant on implementing the
ISerializable interface. To cut a long story short, it's a base
class written in VB that implements ISerializable, but also
knows how to get all the fields of derived objects and add them to the
serialization stream without your derived class having to implement the
GetObjectData method (you still have to add the special
de-serialization constructor though).
Using all my brain power, I came up with an ingenious name for it:
SerializableObject ;-)
Using SerializableObject
To use the serializable object, follow these steps:
- Create your class as normal, except inherit from
SerializableObject instead of Object.
- Add the normal constructor (
Public Sub New()).
- Add the protected de-serialization constructor and simply call the base
class de-serialization constructor.
- Mark your class with the
<Serializable>
attribute.
Example usage in a class:
<Serializable()>
Public Class ObjectThatRaisesEvents
Inherits SerializableObject
Public Sub New()
MyBase.New()
End Sub
Protected Sub New( _
ByVal info As System.Runtime.Serialization.SerializationInfo, _
ByVal context As System.Runtime.Serialization.StreamingContext)
MyBase.New(info, context)
End Sub
End Class
There you go. No more problems with event handlers being serialized!
If you still need to perform some custom serialization, simply override
the base class GetObjectData method, but remember to call
MyBase.GetObjectData to complete the serialization.
SerializableObject also implements the
IDeserializationCallback interface in order to do some
post-deserialization processing (as mentioned below). If you need to be
notified when the OnDeserialization method is called, simply
override it, but again - remember to call
MyBase.OnDeserialization if you do override it!
In the case that your object to be serialized needs to inherit from a
different class (say CollectionBase or ArrayList,
then you can implement the ISerializable interface and use the
shared SerializableObject.SerializeObject() method to populate
the SerializationInfo object. In order to deserialize your
object again, you must implement the de-serialization constructor and the
IDeserializeCallback interface to call the shared
SerializableObject.DeSerializeObject() to repopulate your
object. Please see the sample application for more details on how to do
this.
How it works
As mentioned above, SerializableObject implements the
ISerializable and IDeserializationCallback
interfaces in order to control its own serialization. Instead of relying on
the derived classes to override the GetObjectData method and
serialize themselves, it uses the FormatterServices class and
Reflection to get the names and values of all fields in all the
derived types - even private ones. This way, the derived classes can forget
about serializing every field and leave it up to the base class.
When you serialize an object, the following steps occur:
SerializableObject.GetObjectData method is called by the
runtime.
SerializableObject calls
FormatterServices.GetSerializableMembers to get all fields that
are to be serialized.
SerializableObject removes those fields that are of type
System.Delegate as these are what events are implemented with
and are causing all the trouble.
SerializableObject uses reflection to get the current
values of all the fields and adds them to the serialization stream.
When you deserialize an object, the following steps occur:
- The deserialization constructor is called on your derived object.
- Your derived object calls the base class deserialization constructor.
SerializableObject records the information.
- The
OnDeserialization method is called.
SerializableObject calls
FormatterServices.GetSerializableMembers to get all fields that
are to be de-serialized.
SerializableObject uses reflection to set the current
values of all the serialized fields.
Grey Areas
Although I've tested this as much as possible (including letting it go
into full applications) and have had no problem with it whatsoever, I must
remind you that there could be bugs. I leave it up to you to assess how
useful and safe this code is.
One potential grey area is my knowledge of Security in .NET (i.e. None).
The use of FormatterServices requires special security
privileges. I seemed to get around this problem by using the following
attribute where it was needed:
<SecurityPermission(SecurityAction.Assert, _
Assertion:=True, SerializationFormatter:=True)>
If anyone can suggest a proper way of doing this, let me know.
Another area that I'm not sure about is the lifetime of the
SerializationInfo object that is passed to the de-serialzation
constructor. As you can see from the implementation, I keep a reference to
it between the constructor and the OnDeserialization method
(this is necessecary because variable initializers are called after the
de-serialization constructor and so could overwrite the de-serialized field
values). If the SerializationInfo object becomes invalid
somehow, the de-serialization process might not work anymore.
Points Of Interest
I'm surprised nobody has come up with this approach before (maybe they
did and I just didn't look hard enough). Surely I'm not the only lazy
programmer out there who looks for an easy way out (which I think this is -
at least compared to the other ways around it).
Also, because this problem is caused by not being able to specify the
<NonSerialized> attribute on events in VB.NET,
I hope that this will change in the next version of VB.NET. I guess they
missed it between framework 1.0 and 1.1. If anybody can confirm this, it
would be nice.
History
- V1.1: Article updated for minor mistakes. Changed implementation
of
SerializableObject to use shared methods so you can use the
functionality in your own classes that can't inherit from
SerializableObject. Also updated the sample project to
demonstrate this capability. Again, thanks to Jay B. Harlow and Rowen
McDermott for all the help and advice.
- V1.0: Version first posted to CodeProject.
- V0.1: The first version of
SerializableObject used
reflection exclusively to get all the fields and then determine which ones
should be serialized. Thanks go to Jay B. Harlow for the tip about the
existence of FormatterServices - it made it a lot more
efficient with a few less lines of code.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 45 (Total in Forum: 45) (Refresh) | FirstPrevNext |
|
 |
|
|
Hi, I've used your function to help me serialize a class I've developed.
But I came across an error while serializing an object derived from a non-serializable class.
The solution is farely simple, simply replace the code where the member are located on the GetSerializableMembers function by the code below.
Dim aAllMembers As System.Reflection.MemberInfo() Try '* '* Try to get all the serializable members '* aAllMembers = FormatterServices.GetSerializableMembers(PersistableType) Catch ex As SerializationException '* '* If an error occurred while trying to get all public members '* aAllMembers = PersistableType.GetMembers(BindingFlags.Public) Catch ex As Exception '* '* An exception has occurred '* Throw End Try
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
When I try to serialize object that contains hashTable it works fine.
but while deserialize is in process, first the program deserialize the hashTable and after it, comes to the object that contains it.
Then I have an exception, at the object constructor when I try to use the hashTable.
Thanks Shuli
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
1. Have you got any new insights about this issue? For example, with .NET 2.0 or 3.0, are there any framework changes that makes your solution obsolete? Or any other new concepts?
Assume I insist on serialization due to saving into file or for deep cloning or other things. Now I have the little off-topic questions:
2. Could another design of the appliction solve the problem totally different? I have no idea but maybe someone else. But I don't mean those ideas with splitted classes or implementing ISerializable manually.
3. Why insist on VB and not changeover to C#? Ok, this is discussion about VB vs C#. But it might be reasonable to do the changeover since it is a major disadvantage if serialization is important. Only the core with the model classes could be changed. Or let me ask into the other direction: Is this disadvantage sufficient enough to change the language?
Cheers, Robert
-- modified at 6:57 Thursday 9th November, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Robert,
I'll try and answer these as best as I can.
1) >> with .NET 2.0 or 3.0, are there any framework changes that makes your solution obsolete? Or any other new concepts?
I mentioned in previous post that VB 2005 has a few changes (i.e. Custom Events) that make things easier. As yet, I haven't gotten around to updating the actual article. See the following link for more info:
http://www.codeproject.com/script/comments/user_mail.asp?main=/vb/net/serializevbclasses.asp&df=100&forumid=31606&select=984207[^]
2) >> Could another design of the application solve the problem totally different?
Assuming we're not using VB2005, there are a few designs that come to mind that could get around this problem. At a high level, these include: a) Manage events more carefully (e.g. manually removing all event handlers before serializing the object). b) Using interface callbacks instead of events. You'd have to store the callback objects in your object as a collection marked as <NonSerialized>.
I'm sure there are many more different ways to get around this problem, but they all depend on the situation that you encounter. If you have a specific situation, I'd be glad to try and tackle it with you.
3) >> Why insist on VB and not changeover to C#? <snip> Or let me ask into the other direction: Is this disadvantage sufficient enough to change the language?
I don't think this issue is serious enough to warrant changing languages. A number of reasons exist that make a changeover more difficult than getting around this issue:
a) Even in cases where serialization is important, if you already have a large code base, it probably wouldn't be worth the effort. Even without this utility, implementing ISerializable has got to be easier than the changeover.
b) As mentioned in 2), there are a couple of other solutions that could be employed.
c) Although I believe any senior dotnet developer should be equally comfortable in C# as VB, the fact remains that there's a large VB following that has transitioned from VB6... changing coding language because of a problem like this could introduce a lot more serious bugs.
I hope these answer your questions. Thanks for the feedback... your post has reminded me about this article and that I really should update it to include VB2005's solution!
Take care,
Trev.
-- modified at 9:04 Thursday 9th November, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This is very useful. I have implemented a couple of my classes that expose public events and it's working great.
I have come across a problem implementing a class that inherits from the hashtable and exposes public events. I am overriding the GetObjectData and the OnDeserialize methods following the sample application guidelines. I added the constructor and the mInfo non-serialized property.
When I try to serialize my object, I get the following error as the application exits the SerializeObject sub: The type System.Collections.Hashtable+bucket in Assembly mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is not marked as serializable.
Hanika
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi,
Sorry for not replying sooner. I believe that your problem is because you're using an earlier version of the .Net framework where the hashtable class wasn't serializable. There's two routes you can take.
1) Manually loop through the hashtable entries and add them to the serialization info object in GetObjectData method and then do the reverse in the OnDeserialize method.
2) Use a newer version of the .Net framework where Hashtable is serializable
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I am trying to use your example with state server. The serialization appears to work okay. The problem is with deserialization. The info As SerializationInfo that is passed into the protected constructor of the collection class is nothing. So when a my collection class calls the shared DeserializeObject method all heck breaks loose. I am not certain if I am doing something wrong or if the implementation is not the same for state server. It seems as though it should be since it is Interface based. Let me know if you have any ideas!
Keith N
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Keith,
I've never used the ASP.Net state server, so I can't offer much help on that, but here's a few steps you could try to troubleshoot it:
1) Create a dummy class (call it 'Bob' ), implement ISerializable and the protected constructor and see if the same thing happens. If it does, it's a problem with the state server or how you're using it.
2) Take your classes outside of the State Server and put them into a test harness (e.g. a console application). Try and serialize/deserialize your object graph to/from a file using a standard formatter (soap or binary). Again, if it works, the problem is with the state server.
If you don't get anywhere with the above methods, post a snippet of code that demonstrates the problem and I'll take a peek.
Hope this helps,
Trev.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hey,
I ended up moving the base class and the events with it to C# and used not serialize field attribute. BTW, this is how LHOTKA does all of his stuff; separate assembly in C#. I was lucky enough not to have any events anywhere else. I did take a stripped down object and seriazlized/deserialized it okay to a memory stream. Still did not work with ASP.NET State Server though. Maybe it is a setting or something I am not aware of but thank you! The code looks great...
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
Has anyone else found Rockford's solution (mentioned in previous post) unstable? We get exceptions whenever eventhandlers added at runtime (using AddHandler ...) are processed if we use his solution.
Specifically the line:
If value.Target.GetType.IsSerializable Then....
Will throw an exception if value.Target is null (nothing). Easy enough to test for, but I'm surprised it hasn't been commented on unless we are missing something else?
I certainly prefer the theory of the suggested solution in this article (although I've yet to try it) - ISerializable is how we've done it before - and it's a PAIN, but this would help.
I'm always amazed that such an obvious flaw in VB.NET has not yet been addressed - are so many developers out there still avoiding true OO and n-tier architecture for their apps? (don't answer that one, I know, I know....)
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hai , i want to assign as value to label1 . The value will be comming from the backend datbase . So please give me the soultion . what command i have to use
dim o as dataset
label1.text = o.tables(0).rows(0).coloumns(i)
it is giving error.
Please slove the probel
seshu
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
hi All
first, i'd like to thank trev and the rest of the guys in this thread for the all the info. i'm new to serialization/deserialization and vb.net in general. however, i find myself in a 'deep' trouble, pardon the pun. But i need to do some deep cloning, and after a week of searching on the web, i came to the conclusion that serializing is the way to go. And during this searching, I've stumbled upon this thread.
Trev, I've implemented your serializableobject, after a couple of days (i know, it's sad), i got the my class to serialize, but sadly, i can't deserialize, i'm still getting the "Serialization will not deserialize delegates to non-public methods." error. and for the life of me, I don't understand, as i've stepped through the serialization and saw that the event handlers are being skipped.
i think the problem is, i'm trying to retrofit, cloning (and thus serializing) in a project where all the classes are already in existence, and i've managed to set the attribute to most of the class and where needed.
My question is, do i need to implement the deserialization constructor in each and every class? I don't mean to be pushy, but we have a compile coming up in a couple of days and I would appreciate any help. I know, I've left it a bit late, but I wanted to figure out what's wrong myself before I ask for help (bad move).
Thanks!
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
In answer to your question, you need to implement the protected deserialization constructor in every class that implements ISerializable (or inherits from my SerializableObject class), although I suspect that this isn’t the cause of the error that you’re getting.
For security reasons, you cannot deserialize a delegate that doesn’t point to a public method. Are you using delegates anywhere else in your object that could be causing this? It’s been a while since I’ve looked at my serializable object, so I’m not sure if it just filters event delegates or all delegates – I will have a look this evening and let you know.
If you can identify the delegate that is causing the error, you should be able to get around it by making the method it calls public. It’s not the best solution, but it’s the best that I can offer at the minute.
If you can email me some sample code that demonstrates the problem you’re having, I’d be glad to have a look and see – I can’t guarantee I’ll fix it or get it done right away though.
roshec wrote: I know, I've left it a bit late, but I wanted to figure out what's wrong myself before I ask for help (bad move).
It’s never a bad move to ask for help! (except in exams!)
Trev
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
thanks trev for the response.
first, you're right, i don't think the problem is the deserialization constructor, as i've encountered and patched accordingly.
but u may be right where you said about delegates not pointing to public methods, as i've lots of the floating around. The delegates are marked as public
here's a simplied class where the public delegate is located.
Public Class CashFlow
#Region "Variables" Private _valuationMethod As ValuationDelegate #End Region
#Region "Delegates" Public Delegate Function ValuationDelegate(ByVal invoker As CashFlow, ByVal range As DateRange) As ValuationDetailHashtable #End Region
#Region "Constructors" Public Sub New(ByVal valuationMethod As ValuationDelegate) Me._valuationMethod = valuationMethod End Sub #End Region
But the way we instantiate this is
New CashFlow(AddressOf Me.ValuationAllocatedPension)
And the definition of the delegate method wouldn't be public, it'll be protected friend.
Protected Friend Overridable Function ValuationAllocatedPension(ByVal invoker As CashFlow, ByVal range As DateRange) As CashFlow.ValuationDetailHashtable
The way you filter delegetates is
FormatterServices.GetSerializableMembers(PersistableType) If (Not GetType(System.Delegate).IsAssignableFrom(objField.FieldType)) Then
i'm still trying to get it to work, if i have more info, u bet i'll be posting more here.
i'm sorry i couldn't provide more code, 'coz like i've said in my first post, i'm trying to retrofit serialization, and i don't think it's appropriate to post long codes as this could be more confusing. This post is long enough as it is..
thanks again.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Hi,
Based on the sample code you gave me, I was able to recreate the error you’re having with a simple class. As far as I can see, there are two ways around this:
1) Inherit your base class from my Serializable object class. Don’t forget to implement the proper constructor in each derived class. You’ll also probably want to override the OnDeserialization method so you can “reconnect” your delegates after deserialization.
2) Implement ISerializable and IDeserializationCallback in your classes. Manually serialize your class in the ISerializable.GetObjectData method (leaving out the delegates). Reconnect your delegates in the IDeserializationCallback.OnDeserialization method. You’ll need to make both of the above methods Protected Overridable so you can serialize and deserialize all your derived classes.
Let me know if you need a more info or if you need some sample code.
Hope this helps,
Trev.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi trev,
thanks again trev, yes, more info/sample code would really come in handy if you don't mind.
I might try your No.1 option, 'coz No.2 sounds a bit more tedious I think.
Here's what i did to recreate the problem with your SerializationTest project
I created two classes, one is a must inherit class with one interface in it, and another that inherits the mustinherit class. Then i added a property in the GoodObjectThatRaisesEvents class, also added a PRIVATE event handler which throws the error.
_ Public Class InheritTheMustInheritClass Inherits MustInheritClass Public Sub New() End Sub End Class
_ Public MustInherit Class MustInheritClass Implements IDataCollection Public Sub New() End Sub
#Region "Events" Public Event DataCollectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Implements IDataCollection.DataCollectionChanged #End Region
End Class
Public Interface IDataCollection
#Region "Events" Event DataCollectionChanged(ByVal sender As Object, ByVal e As EventArgs) #End Region
End Interface
I then added a variable/property in GoodObjectThatRaisesEvents.
Private _inheritTheClass As InheritTheMustInheritClass
Public Property TestClass() As InheritTheMustInheritClass Get Return Me._inheritTheClass End Get Set(ByVal Value As InheritTheMustInheritClass) Me._inheritTheClass = Value End Set End Property
Instantiated the InheritTheMustInheritClass and add an event handler in the default constructor
Me.TestClass = New InheritTheMustInheritClass
AddHandler Me.TestClass.DataCollectionChanged, AddressOf Me.HandleChanged
and made the handler private as such
PRIVATE Sub HandleChanged(ByVal sender As Object, ByVal e As EventArgs) End Sub
This produces the error as discussed, and error disappears when the handler method is set to PUBLIC.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
hi trev,
got it to work!, made all those event method handlers public
(eg addhandler me.test.changed, addressof me.handle_Test_Changed PUBLIC sub handle_Test_Changed)
i know it's crap way of fixing it, but hey it works.
any suggestion would be welcome
thanks again
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Heya,
Sorry for the delay in getting back about this. Busy week :S
Anyway, here's a few sample classes that I've come up with to get around the problem (without resorting to making the handlers public . Let me know if you have any trouble with the examples.
Example 1: Demonstrates the error. It will throw an exception when deserializing. Although it doesn't follow your inheritance pattern, it should be easy to understand what's going on.
<Serializable()> Public Class PrivateDelegateClass
Public Delegate Sub TheEventDelegate() Public Event TheEvent As TheEventDelegate
Public Sub New() AddHandler Me.TheEvent, AddressOf TheEventHandler End Sub
Private Sub TheEventHandler() Debug.WriteLine("hello") End Sub
End Class
Example 2: Gets around the problem by inheriting from SerializableObject. This may be complicated to build into your inheritance structure as the base class will need to inherit from it.
<Serializable()> Public Class PrivateDelegateClass1 Inherits SerializableObject
Public Delegate Sub TheEventDelegate() Public Event TheEvent As TheEventDelegate
Public Sub New() AddHandler Me.TheEvent, AddressOf TheEventHandler End Sub ' Deserialization constructor Protected Sub New(ByVal info As SerializationInfo, _ ByVal context As StreamingContext) MyBase.New(info, context) End Sub
' Deserialization callback - used to reconnect delegates Protected Overrides Sub OnDeserialization(ByVal Sender As Object)
AddHandler Me.TheEvent, AddressOf TheEventHandler
MyBase.OnDeserialization(Sender)
End Sub
Private Sub TheEventHandler() Debug.WriteLine("hello") End Sub
End Class
Example 3: Implements ISerializable and IDeserializationCallback to manually serialize the class. If you use inheritance, it's best to implement these in the base class and override them in derived classes so each class can serialize/deserialize itself.
<Serializable()> Public Class PrivateDelegateClass2 Implements ISerializable, _ IDeserializationCallback
Public Delegate Sub TheEventDelegate() Public Event TheEvent As TheEventDelegate
Public Sub New() AddHandler Me.TheEvent, AddressOf TheEventHandler End Sub ' Deserialization constructor Protected Sub New(ByVal info As SerializationInfo, _ ByVal context As StreamingContext) ' Deserialize your fields from this constructor (Reverse of GetObjectData) End Sub
Private Sub TheEventHandler() Debug.WriteLine("hello") End Sub
Private Sub GetObjectData(ByVal info As SerializationInfo, _ ByVal context As StreamingContext) _ Implements ISerializable.GetObjectData ' Use this method to add data to the "info" property bag ' e.g. ' info.AddValue "PropertyName", PropertyValue End Sub
Private Sub OnDeserialization(ByVal sender As Object) _ Implements IDeserializationCallback.OnDeserialization
' Reconnect the event handlers AddHandler Me.TheEvent, AddressOf TheEventHandler
End Sub End Class
HTH,
Trev.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I've just encountered another VB serialization problem. If you use a local static variable in a sub/function of a serializable class then you get an error when you attempt to serialize the object (something like "StaticLocalInitFlag not marked as serializable")
eg
_ public class Foo
public Sub Bar() ' causes problems with serialization static myVar as boolean = true end sub
The workaround is to not use statics in these cases (either use normal member variables or consts)
end class
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Well spotted Grant. I never noticed this before. I'll have a look at my SerializableObject class and see what I can do to improve it so it can handle this situation.
Cheers,
Trev
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I came across this issue a while ago and after banging my head for a while came up with the following solution.
Use delegates rather than events and declare the delegate variable as non-serializable.
eg
Delegate Sub ChangeHandler()
Protected mChangeHandler As ChangeHandler
Public Sub AddChangeHandler(ByVal sHandler | | | | | |