{"id":973,"date":"2009-12-14T17:21:00","date_gmt":"2009-12-14T17:21:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2009\/12\/14\/hidden-gems-in-vb2010-serializing-objects-that-raise-events-jonathan-aneja\/"},"modified":"2024-07-05T12:42:12","modified_gmt":"2024-07-05T19:42:12","slug":"hidden-gems-in-vb2010-serializing-objects-that-raise-events-jonathan-aneja","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/hidden-gems-in-vb2010-serializing-objects-that-raise-events-jonathan-aneja\/","title":{"rendered":"Hidden Gems in VB2010 &#8211; Serializing Objects that Raise Events (Jonathan Aneja)"},"content":{"rendered":"<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">By now you&#8217;ve likely heard about the major <a href=\"http:\/\/code.msdn.microsoft.com\/vbfuture\/Release\/ProjectReleases.aspx?ReleaseId=1699\">new features<\/a> coming in VB 2010, but there&#8217;s also a number of smaller additions in the language and IDE that might not be as readily noticeable.&nbsp; &#8220;Hidden Gems&#8221; will be a multi-part series where we&#8217;ll explore some of these smaller enhancements.&nbsp; First up &#8211; serialization!<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\"><\/font><\/font><\/span>&nbsp;<\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Let&rsquo;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.&nbsp; 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.&nbsp; For example, if a Form was handling the event raised from this class, the class can no longer be serialized.<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\"><span>In C# the solution is simple &ndash; just use a field attribute target to tell the serializer not to attempt to serialize the delegate and any objects it references<\/span>:<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span>[<span>field<\/span>: <span>NonSerialized<\/span>]<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>event<\/span> <span>PropertyChangedEventHandler<\/span> PropertyChanged;<\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\"><font face=\"Calibri\">VB doesn&rsquo;t support attribute targets for fields though, so the way to work around this is to use a custom event:<b><\/p>\n<p><\/b><\/font><\/font><\/p>\n<p class=\"MsoNoSpacing\"><b><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/b><\/p>\n<p class=\"MsoNormal\"><span>&lt;Serializable()&gt; <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Public<\/span><span> <span>Class<\/span> Customer<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp; <\/span><span>&nbsp;&nbsp;<\/span><span>Implements<\/span> INotifyPropertyChanged<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span>&lt;NonSerialized()&gt; <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> _PropertyChanged <span>As<\/span> PropertyChangedEventHandler<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Public<\/span> <span>Custom<\/span> <span>Event<\/span> PropertyChanged <span>As<\/span> PropertyChangedEventHandler _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Implements<\/span> INotifyPropertyChanged.PropertyChanged<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>AddHandler<\/span>(<span>ByVal<\/span> value <span>As<\/span> PropertyChangedEventHandler)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_PropertyChanged = <span>CType<\/span>([Delegate].Combine(_PropertyChanged,<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>value), PropertyChangedEventHandler)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>AddHandler<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>RemoveHandler<\/span>(<span>ByVal<\/span> value <span>As<\/span> PropertyChangedEventHandler)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_PropertyChanged = <span>CType<\/span>([Delegate].Remove(_PropertyChanged,<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>value), PropertyChangedEventHandler)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>RemoveHandler<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>RaiseEvent<\/span>(<span>ByVal<\/span> sender <span>As<\/span> <span>Object<\/span>, <span>ByVal<\/span> e <span>As<\/span> PropertyChangedEventArgs)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> _PropertyChanged <span>IsNot<\/span> <span>Nothing<\/span> <span>Then<\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_PropertyChanged.Invoke(sender, e)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>End If<\/span><span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>RaiseEvent<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Event<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span>&#8230;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>End<\/span><span> <span>Class<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNoSpacing\">\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">(For a more thorough implementation see Rocky&rsquo;s excellent <\/font><a href=\"http:\/\/www.lhotka.net\/weblog\/BetterVersionOfTheNET20EventserializationSolution.aspx\"><font color=\"#0000ff\" size=\"3\" face=\"Calibri\">blog entry<\/font><\/a><font size=\"3\"><font face=\"Calibri\">).<span>&nbsp; <\/span>That&rsquo;s a lot of code to write though &ndash; <i>basically you&rsquo;re having to take control of the backing field yourself just to apply the attribute manually.<\/p>\n<p><\/i><\/font><\/font><\/p>\n<p class=\"MsoNoSpacing\">\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNoSpacing\"><b><font size=\"3\"><font face=\"Calibri\">How does VB2010 help?<\/p>\n<p><\/font><\/font><\/b><\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">We now allow the NonSerialized attribute to be placed on an Event.&nbsp; The compiler will&nbsp;then:<\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font size=\"3\" face=\"Calibri\">1.<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\" face=\"Calibri\">Suppress the error that says &ldquo;this attribute cannot be used on this type of declaration&rdquo;<\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font size=\"3\" face=\"Calibri\">2.<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\" face=\"Calibri\">Apply the NonSerialized attribute to the event&rsquo;s backing field.<\/font><\/p>\n<p class=\"MsoNoSpacing\">\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNoSpacing\"><font size=\"3\" face=\"Calibri\">As a result you&rsquo;ll be able to type the following in VB 2010 (try it, it works in <a href=\"http:\/\/msdn.microsoft.com\/en-us\/vstudio\/dd582936.aspx\">Beta2<\/a>!):<\/font><\/p>\n<p class=\"MsoNoSpacing\">\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span>&lt;NonSerialized()&gt; <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>\n<span>&nbsp;&nbsp;&nbsp; <\/span><span>Event<\/span> PropertyChanged <span>As<\/span> PropertyChangedEventHandler<\/p>\n<p><\/span><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>By now you&#8217;ve likely heard about the major new features coming in VB 2010, but there&#8217;s also a number of smaller additions in the language and IDE that might not be as readily noticeable.&nbsp; &#8220;Hidden Gems&#8221; will be a multi-part series where we&#8217;ll explore some of these smaller enhancements.&nbsp; First up &#8211; serialization! &nbsp; Let&rsquo;s [&hellip;]<\/p>\n","protected":false},"author":260,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[195],"tags":[72,83,167],"class_list":["post-973","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-visual-basic","tag-hidden-gems-in-vb10","tag-jonathan-aneja","tag-vb2010"],"acf":[],"blog_post_summary":"<p>By now you&#8217;ve likely heard about the major new features coming in VB 2010, but there&#8217;s also a number of smaller additions in the language and IDE that might not be as readily noticeable.&nbsp; &#8220;Hidden Gems&#8221; will be a multi-part series where we&#8217;ll explore some of these smaller enhancements.&nbsp; First up &#8211; serialization! &nbsp; Let&rsquo;s [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/973","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/260"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=973"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/973\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}