Cannot serialize class `ObservableDictionary <TKey, TValue>`
I wrote my class public sealed class ObservableDictionary<TKey,TValue> : NotifyPropertyChangedClass, INotifyCollectionChanged, IDictionary<TKey, TValue> where TKey: IEquatable<TKey> .
It is marked as [Serializable] .
But I got an exception when I tried to serialize an instance of ObservableDictionary<Int64, String> .
Exception Message:
The type MS.Internal.Data.EnumerableCollectionView in the assembly "PresentationFramework, Version = 4.0.0.0, Culture = neutral" is not marked as PublicKeyToken = 31bf3856ad364e35 as serializable.
But I never used the type MS.Internal.Data.EnumerableCollectionView .
Where is my mistake? My code below is located:
using System; using System.ComponentModel; namespace RememberEmployees { [Serializable] public abstract class NotifyPropertyChangedClass : INotifyPropertyChanged { protected void NotifyPropertyChanged(string propertyName) { PropertyChangedEventHandler temp = PropertyChanged; if (temp != null) { temp(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; } } and
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Collections.Specialized; namespace RememberEmployees { [Serializable] public sealed class ObservableDictionary<TKey,TValue> : NotifyPropertyChangedClass, INotifyCollectionChanged, IDictionary<TKey, TValue> where TKey: IEquatable<TKey> { SortedDictionary<TKey, TValue> dict; IComparer<TKey> Comparer { get { return dict.Comparer; } } public ObservableDictionary() { dict = new SortedDictionary<TKey, TValue>(); IsReadOnly = false; } private void NotifyCollectionChanged(NotifyCollectionChangedAction action) { NotifyCollectionChangedEventHandler temp = CollectionChanged; if (temp != null) { temp(this, new NotifyCollectionChangedEventArgs(action)); } } private void NotifyCollectionChanged(NotifyCollectionChangedAction action, object item) { NotifyCollectionChangedEventHandler temp = CollectionChanged; if (temp != null) { temp(this, new NotifyCollectionChangedEventArgs(action, item)); } } private void NotifyCollectionChanged(NotifyCollectionChangedAction action, int index) { NotifyCollectionChangedEventHandler temp = CollectionChanged; if (temp != null) { temp(this, new NotifyCollectionChangedEventArgs(action, index)); } } private void NotifyCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> obj, int index) { NotifyCollectionChangedEventHandler temp = CollectionChanged; if (temp != null) { temp(this, new NotifyCollectionChangedEventArgs(action, obj, index)); } } public event NotifyCollectionChangedEventHandler CollectionChanged; public void Add(TKey key, TValue value) { if (IsReadOnly) throw new Exception("Is Read Only"); dict.Add(key, value); NotifyPropertyChanged("Count"); NotifyCollectionChanged(NotifyCollectionChangedAction.Add, dict.Cast<KeyValuePair<TKey, TValue>>().FirstOrDefault(n => n.Key.Equals(key))); } public bool ContainsKey(TKey key) { return dict.ContainsKey(key); } public ICollection<TKey> Keys { get { return dict.Keys; } } public bool Remove(TKey key) { if (IsReadOnly) throw new Exception("Is Read Only"); if (!dict.Keys.Contains(key)) return false; int x = 0; foreach (TKey item in dict.Keys) { if (item.Equals(key)) break; ++x; } KeyValuePair<TKey, TValue> val = dict.Cast<KeyValuePair<TKey, TValue>>().FirstOrDefault(n => n.Key.Equals(key)); bool result = dict.Remove(key); if (result) { NotifyPropertyChanged("Count"); NotifyCollectionChanged(NotifyCollectionChangedAction.Remove, val, x); } return result; } public bool Remove(KeyValuePair<TKey, TValue> item) { return Remove(item.Key); } public bool TryGetValue(TKey key, out TValue value) { return dict.TryGetValue(key, out value); } public ICollection<TValue> Values { get { return dict.Values; } } public TValue this[TKey key] { get { return dict[key]; } set { dict[key] = value; NotifyCollectionChanged(NotifyCollectionChangedAction.Reset); } } public void Add(KeyValuePair<TKey, TValue> item) { Add(item.Key, item.Value); } public void Clear() { if (IsReadOnly) throw new Exception("Is Read Only"); dict.Clear(); NotifyCollectionChanged(NotifyCollectionChangedAction.Reset); } public bool Contains(KeyValuePair<TKey, TValue> item) { return dict.Contains(item); } public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { if (arrayIndex > dict.Count) throw new IndexOutOfRangeException(); int max = dict.Count - arrayIndex <= array.Count() ? dict.Count - arrayIndex : array.Count(); for (int i = 0; i < max; i++) { array[i] = dict.Skip(arrayIndex).ToArray()[i]; } } public int Count { get { return dict.Count; } } bool readOnly; public bool IsReadOnly { get { return readOnly; } set { readOnly = value; NotifyPropertyChanged("IsReadOnly"); } } public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return dict.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return dict.GetEnumerator(); } } } This is not only related to your class, but also to the data that you saved in your collection. It seems that in your collection you have saved the ViewObject, which inside contains the EnumerableCollectionView.
When you serialize data, you need to be sure which parts of your feature graph you want to serialize. Just placing objects in your collection can cause half of your application data to be sent by wire or to disk. There is a good reason DataContractSerializer was invented.
Before you serialize a call, you must know what data you are going to serialize. Otherwise, this can happen, for example, in a client server application you are trying to deserialize types that are located in assemblies that exist only on the server.