Serialization And Event Subscriptions

posted on 10/19/07 at 12:20:47 am by Joel Ross

We ran into an interesting issue with Pay It Square and the NuSoft Framework tonight with a change we made as part of the 2.0 release of the framework. We changed our collections to inherit from BindingList<T> instead of List<T>, and we thought it would be a simple change that allows us to better support two-way binding.

Well, as with any change, there were some unintended side effects. Actually, it's an issue that has always been there, but only manifested itself once we started using BindngList<T>. You can reproduce this issue pretty simply. Create the following class.:

[Serializable()]
public class EventSample
{
public event EventHandler MyPropertyChanged;

protected void OnMyPropertyChaged()
{
if(MyPropertyChanged != null)
{
MyPropertyChanged(
this, EventArgs.Empty);
}
}

private string _myProperty;
public string MyProperty
{
get { return _myProperty; }
set
{
if (_myProperty == value)
{
return;
}
_myProperty
= value;
OnMyPropertyChaged();
}
}
}

Note it's marked as serializable and has one public event. Now create a simple web page, with the following code:

protected void Page_Load(object sender, EventArgs e)
{
EventSample sample
= new EventSample();

sample.MyPropertyChanged

+= new EventHandler(sample_MyPropertyChanged);

ViewState[

"Sample"] = sample;
}

void sample_MyPropertyChanged(object sender, EventArgs e)
{
Response.Write(
"My Property Changed");
}

When you load the page, you'll get an error because the subscriptions cannot be serialized.

As it turns out, the solution is not really that difficult. Basically, you tell .NET to ignore your event when serializing, but the syntax is a little different than what you'd expect.

[field: NonSerialized()]
public event EventHandler MyPropertyChanged;

You're not really telling .NET not to serialize the event - you're telling .NET not to serialize the field that is created for you automagically to hold references to subscribers. A side effect of this is that your event subscriptions will go away when the object is de-serialized, so be aware of that.

So how did changing our EntityList to inherit from BindingList<T> reveal all this? Well, we were putting a collection into ViewState, and the way BindingList<T> helps in handling two-way binding is by looking at objects added to it and if they support the INotifyPropertyChanged interface, and if it does, the list subscribes to the event - and therefore, returns an error when you attempt to serialize it.

Categories: Development, C#, RCM Technologies