Hidden Gems in VB2010 – Serializing Objects that Raise Events (Jonathan Aneja)

VBTeam

By now you’ve likely heard about the major new features coming in VB 2010, but there’s also a number of smaller additions in the language and IDE that might not be as readily noticeable.  “Hidden Gems” will be a multi-part series where we’ll explore some of these smaller enhancements.  First up – serialization!

 

Let’s say you have a simple entity class that you need to serialize and send over the wire. This class implements INotifyPropertyChanged which contains an event.  When attempting to serialize an instance of this class, if the delegate which backs the event has its Target property referencing an Object which is not serializable, then the entity class itself can no longer be serialized.  For example, if a Form was handling the event raised from this class, the class can no longer be serialized.

In C# the solution is simple – just use a field attribute target to tell the serializer not to attempt to serialize the delegate and any objects it references:

    [field: NonSerialized]

    public event PropertyChangedEventHandler PropertyChanged;

 

VB doesn’t support attribute targets for fields though, so the way to work around this is to use a custom event:

 

<Serializable()>

Public Class Customer

    Implements INotifyPropertyChanged

 

    <NonSerialized()>

    Private _PropertyChanged As PropertyChangedEventHandler

 

    Public Custom Event PropertyChanged As PropertyChangedEventHandler _

        Implements INotifyPropertyChanged.PropertyChanged

 

        AddHandler(ByVal value As PropertyChangedEventHandler)

            _PropertyChanged = CType([Delegate].Combine(_PropertyChanged,

                                     value), PropertyChangedEventHandler)

        End AddHandler

 

        RemoveHandler(ByVal value As PropertyChangedEventHandler)

            _PropertyChanged = CType([Delegate].Remove(_PropertyChanged,

                                     value), PropertyChangedEventHandler)

        End RemoveHandler

 

      RaiseEvent(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)

          If _PropertyChanged IsNot Nothing Then       

              _PropertyChanged.Invoke(sender, e)

          End If

      End RaiseEvent

    End Event

 

   

End Class

 

(For a more thorough implementation see Rocky’s excellent blog entry).  That’s a lot of code to write though – basically you’re having to take control of the backing field yourself just to apply the attribute manually.

 

How does VB2010 help?

We now allow the NonSerialized attribute to be placed on an Event.  The compiler will then:

1.       Suppress the error that says “this attribute cannot be used on this type of declaration”

2.       Apply the NonSerialized attribute to the event’s backing field.

 

As a result you’ll be able to type the following in VB 2010 (try it, it works in Beta2!):

 

    <NonSerialized()>

    Event PropertyChanged As PropertyChangedEventHandler

0 comments

Leave a comment

Feedback usabilla icon