Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Serialization and Events : Page 3

Serialization process can result to problems when serializing objects that expose events. This is due to events handling in .NET. This paper describes two techniques to solve this problem, then it exposes some considerations about events and object lifecycle.


Detaching and Attaching Events

An interesting solution to the serialization problem we are discussing is the possibility to "detach" events from an object.
This can be done setting to nothing the EventNameEvent fields. The technique applied to serialization is the following:

  1. Stepping through the EventNameEvent fields, cashing the values (Multicast Delegates) in a collection and setting the field value to nothing
  2. Serialize the object
  3. Stepping through the EventNameEvent fields and restoring the original values.

' Detaches Events before serialization Dim Evt As New Collection() Dim EvtInfo() As Reflection.EventInfo = ser1.GetType.GetEvents() Dim i As Integer 'Finds all events For i = 0 To EvtInfo.GetLength(0) - 1 Dim FldName As String = EvtInfo(i).Name + "Event" ' Get the hidden field (MulticastDelegate) Dim FldInfo As Reflection.FieldInfo = ser1.GetType.GetField(FldName, _ Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance) ' Save the Delegate in a collection Evt.Add(FldInfo.GetValue(ser1), FldName) ' Sets the field value to nothing FldInfo.SetValue(ser1, Nothing) Next ' It is possible to serialize the object without problems fs1 = New FileStream("ser1", FileMode.Create) f1 = New BinaryFormatter(Nothing, New StreamingContext(StreamingContextStates.File)) f1.Serialize(fs1, ser1) fs1.Close() ' Attaches Events after serialization For i = 0 To EvtInfo.GetLength(0) - 1 Dim FldName As String = EvtInfo(i).Name + "Event" Dim FldInfo As Reflection.FieldInfo = ser1.GetType.GetField(FldName, _ Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance) FldInfo.SetValue(ser1, Evt.Item(FldName)) Next

Notes on the previous techniques

Comparing the two solutions explained we should notice that the first one is much better in terms of design.
The serialization logic is "encapsulated" inside the object and the object "solves its own problems" by itself. Any other procedure that has to serialize the object does not need to guess whether the object will have problems with events.
The second solution implies that the serializer procedure knows that the object can have problems due to events and detaches events before serializing.
On the other hand, as far as performance is concerned, the second solution should be much better.

More on Events

The fact that an objects that exposes events keeps a reference to all the listener has major consequences.

The most important one is that the listener should remove event handler to go out of scope.

Consider the following code:

Dim ser1 As New Serialize1() Dim lst1 As New Listener1(ser1, "1") ' Test that the object lst1 responds correctly to event ser1.TestEvent ser1.GenerateEvent()

After the execution of the following code we will see that lst1 is still responding to the event raised by ser1

lst1 = nothing ser1.GenerateEvent()

What is even worse is that the following code will not destroy object lst1

Gc.Collect() Gc.WaitForPendingFinalizers()

Another problem connected with this behavior is that all objects implementing IDisposable should also detach event handlers in the Dispose procedure. If this is not the case the event handler procedures will respond to event also if the object has been disposed, probably referring to objects that are no more alive. This is particularly true with forms as forms dispose all the controls in the Dispose sub.

As a conclusion we should say that all objects which declares variables WithEvents should implement IDisposable and should detach the event handlers in IDisposable.Dispose.


We saw that the serialization process can lead to problems when serializing objects that expose events.

We described two techniques to avoid this problem, the first one implementing a particular personalized serialization, the other one detaching events before serializing objects.

As a last point we reported some considerations on interaction of events and object lifecycle, stating that each object which have a variable declared WithEvents should implement IDisposable and detach event handlers in IDisposable.Dispose procedure.

Andrea Zanetti (andrea_zanetti@cimolai.com) and Riccardo Munisso (riccardo_munisso@cimolai.com) work for Cimolai one of the major european structural steelwork fabricator. They are developing personalized application with SQL Server and .NET. The solutions range from logistic to CAM system.

The VB2TheMax team gathers a number of Italian VB experts and technical writers, some of which are also known abroad for their work as magazine contributors, book authors, and consultants. Our intention is to create an even-growing repository of knowledge about Visual Basic and related technologies, where other developers can find answers to their doubts, and solutions to their problems.All the members of the team are also available for on-line or on-site consulting, training and mentoring.

This isn't a "closed" group, and we're looking for new contributors. If you want to contribute with tips, bug reports, utilities and articles, please contact us. Of course you'll get the credit of your contribution and, if you wish, we can add a link to your home page or email address.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date