Home Dashboard Directory Help
Search

System.Collections.ObjectModel.ReadOnlyObservableCollection<T> not marked serializable by Mike Kenyon


Status: 

Closed
 as Fixed Help for as Fixed


3
0
Sign in
to vote
Type: Suggestion
ID: 285288
Opened: 6/29/2007 1:40:26 PM
Access Restriction: Public
0
Workaround(s)
view

Description

The System.Collections.ObjectModel.ReadOnlyObservableCollection<T> type is not currently marked as serializable, unlike System.Collections.ObjectModel.ObservableCollection<T> and System.Collections.ObjectModel.ReadOnlyCollection<T> which are both marked as Serializable. This has led to several required workarounds to ensure both read control and bindability.
Details
Sign in to post a comment.
Posted by Andy Bird on 8/2/2007 at 6:04 AM
Hi

I've also run into difficulties because ReadOnlyObservableCollection is not marked as serializable.

I have a class with a read only property that returns a ReadOnlyObservableCollection. The class is marked as Serializable. I can serialise instances of the class if I don't access this property in client code, but if I access the property I get a SerializationException when attempting to serialise an instance of the class.

Here's a very simplified example of the class:

[Serializable]
public class MyClass
{
public MyClass()
{
_strings.Add("One");
_strings.Add("Two");
_strings.Add("Three");
}
public ReadOnlyObservableCollection<string> ObservableStrings
{
get
{
return new ReadOnlyObservableCollection<string>(_strings);
}
}
public ReadOnlyCollection<string> Strings
{
get
{
return new ReadOnlyCollection<string>(_strings);
}
}
ObservableCollection<string> _strings = new ObservableCollection<string>();
}

The following code works fine:

MyClass c = new MyClass();
using (Stream stream = File.OpenWrite("@c:\MyClass.bin"))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, c);
}

as does the following:
MyClass c = new MyClass();
ReadOnlyCollection<string> strings = c.Strings;
using (Stream stream = File.OpenWrite("@c:\MyClass.bin"))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, c);
}

BUT the following causes the SerializationException with the error message indicating the problem is that ReadOnlyObservableCollection is not marked as serializable:

MyClass c = new MyClass();
ReadOnlyObservableCollection<string> observableStrings = c.ObservableStrings;
using (Stream stream = File.OpenWrite("@c:\MyClass.bin"))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, c);
}

I'm guessing that the problem is that the ReadOnlyObservableCollection that wraps the private ObservableCollection is connected to the events on the INotifyCollectionChanged and INotifyPropertyChanged interfaces supported by the ObservableCollection that its wrapping. And when the formatter attempts to serialise the object it is seeing these connections in the object graph and trying to serialise the ReadOnlyObservableCollection which is not marked as Serializable (unlike all the other classes in the System.Collections.ObjectModel namespace).

This makes the use of ReadOnlyObservableCollection rather problematic in any situation where serialization is required. Since its primary use is to help with connecting businness layer objects to the UI and the business layer objects likely to need to be serialised this is quite a limitation. Its also rather difficult to track down issues relating to this limitation since the exception will only occur if an instance of a ReadOnlyObservableCollection that is connect to one of the business object's fields is actually instantiated, meaning that some code paths will succeed while others fail (thank goodness we use unit testing extensively).

In this kind of situation we don't really want the ReadOnlyObservableCollection instance(s) to be serialised along with MyClass, but we do need to be able to serialize MyClass after accessing properties that return instances of ReadOnlyObservableCollection, so I'm not sure that just marking it as Serializable is the complete answer. Possibly marking the event delegates for the in the INotifyCollectionChanged and INotifyPropertyChanged interface events implemented in the ObservableCollection class as NonSerializable is also required?

Andy
Sign in to post a workaround.