views:

109

answers:

1

Questions - (Relative Code Below)

  • I have a custom class which is a BindableDictionary().
  • I want to make it serializable.
  • How would I Serialize this?

Thoughts

  • Will The serialization still work if the TValue of the BindableDictionary is a custom object that has another BindableDictionary as a property?
  • So my question is, will both the Top Level BindableDictionary, and the BindableDictionary property of the Top Levels TValue both serialize correctly?

    public class MyClass
    {
        public string Name { get; set; }
        public BindableDictionary<string, MySubClass> SubDictionary { get; private set; }
        public MyClass(string name)
        {
            Name = name;
            SubDictionary = new BindableDictionary<string, MySubClass>();
        }
    }
    
    
    public class MySubClass
    {
        public int Age { get; set; }
        public double Height { get; set; }
        public double Weight { get; set; }
    
    
    public MySubClass()
    {
    
    
    }
        public MySubClass(int age,double height, double weight)
        {
            Age = age;
            Height = height;
            Weight = weight;
        }
    }
    

Class To Serialize

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections;

namespace CommTraderCommon.HelperObjects
{
    public class BindableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IBindingList
    {
        private Dictionary<TKey, TValue> source = new Dictionary<TKey, TValue>();
        private Dictionary<int, TKey> sourceKey = new Dictionary<int, TKey>();

        void IBindingList.AddIndex(PropertyDescriptor property) { }
        object IBindingList.AddNew() { throw new NotImplementedException(); }
        bool IBindingList.AllowEdit { get { return false; } }
        bool IBindingList.AllowNew { get { return false; } }
        bool IBindingList.AllowRemove { get { return false; } }
        void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) { }
        int IBindingList.Find(PropertyDescriptor property, object key) { throw new NotImplementedException(); }
        bool IBindingList.IsSorted { get { return false; } }
        void IBindingList.RemoveIndex(PropertyDescriptor property) { }
        void IBindingList.RemoveSort() { }
        ListSortDirection IBindingList.SortDirection { get { return ListSortDirection.Ascending; } }
        PropertyDescriptor IBindingList.SortProperty { get { return null; } }
        bool IBindingList.SupportsChangeNotification { get { return true; } }
        bool IBindingList.SupportsSearching { get { return false; } }
        bool IBindingList.SupportsSorting { get { return false; } }
        int System.Collections.IList.Add(object value) { throw new NotImplementedException(); }
        void System.Collections.IList.Clear() { Clear(); }
        bool System.Collections.IList.Contains(object value) { if (value is TKey) { return source.ContainsKey((TKey)value); } else if (value is TValue) { return source.ContainsValue((TValue)value); } return false; }
        int System.Collections.IList.IndexOf(object value) { return -1; }
        void System.Collections.IList.Insert(int index, object value) { throw new NotImplementedException(); }
        bool System.Collections.IList.IsFixedSize { get { return false; } }
        bool System.Collections.IList.IsReadOnly { get { return true; } }
        void System.Collections.IList.Remove(object value) { if (value is TKey) { Remove((TKey)value); } }
        void System.Collections.IList.RemoveAt(int index) { throw new NotImplementedException(); }

        object System.Collections.IList.this[int index]
        {
            get
            {
                return source[sourceKey[index]];
            }
            set { throw new NotImplementedException(); }
        }

        private ListChangedEventHandler listChanged;

        event ListChangedEventHandler IBindingList.ListChanged
        {
            add { listChanged += value; }
            remove { listChanged -= value; }
        }

        protected virtual void OnListChanged(ListChangedEventArgs e)
        {
            var evt = listChanged;

            if (evt != null) evt(this, e);
        }

        public void Add(TKey key, TValue value)
        {
            source.Add(key, value);
            sourceKey.Add(sourceKey.Count, key);
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

        public bool Remove(TKey key)
        {
            if (source.Remove(key))
            {
                OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));

                return true;
            }

            return false;
        }

        public TValue this[TKey key]
        {
            get
            {
                return source[key];
            }
            set
            {
                source[key] = value;

                OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
            }
        }

        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
        {
            ((ICollection<KeyValuePair<TKey, TValue>>)source).Add(item);

            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
        {
            if (((ICollection<KeyValuePair<TKey, TValue>>)source).Remove(item))
            {
                OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));

                return true;
            }

            return false;
        }

        public bool ContainsKey(TKey key) { return source.ContainsKey(key); }
        public ICollection<TKey> Keys { get { return source.Keys; } }
        public bool TryGetValue(TKey key, out TValue value) { return source.TryGetValue(key, out value); }
        public ICollection<TValue> Values { get { return source.Values; } }
        public void Clear() { source.Clear(); }
        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) { return ((ICollection<KeyValuePair<TKey, TValue>>)source).Contains(item); }
        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { ((ICollection<KeyValuePair<TKey, TValue>>)source).CopyTo(array, arrayIndex); }
        public int Count { get { return source.Count; } }
        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly { get { return ((ICollection<KeyValuePair<TKey, TValue>>)source).IsReadOnly; } }
        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return source.GetEnumerator(); }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
        bool ICollection.IsSynchronized { get { return false; } }
        object ICollection.SyncRoot { get { return null; } }
        void ICollection.CopyTo(Array array, int arrayIndex) { ((ICollection)source).CopyTo(array, arrayIndex); }
    }
}
+1  A: 

Serialization is not a problem if you only serialize objects that are marked with the Serializable attribute. In your code I do not see this attribute (yet) so your BindableDictionary is not serializable.

There shouldn't be a problem serializing objects that refer to objects of the same type (i.e. when TValue is a BindableDictionary).

Ronald Wildenberg
The only catch is that you cannot XML serialize a Dictionary except by doing so manually.
Alex Essilfie
Can I not just mark the PropertyDescriptor as [NonSerialized] ?
Goober
That would solve the problem. It may be a problem in other parts of your application however that expect a SortProperty.
Ronald Wildenberg
Ok marking the property as [NonSerialized] didn't work, gave me this error - "Attribute 'NonSerialized' is not valid on this declaration type. It is only valid on 'field' declarations."......Hmm, next idea....
Goober
Hm, hadn't thought of that. But I see only now that SortProperty doesn't have a backing field. Binary serialization serializes fields, not properties so in that case marking BindableDictionary as Serializable should be enough. Have you already tried serializing this object?
Ronald Wildenberg
But surely I would have to manually serialize BindableDictionary as well as adding the [Serializable] attribute?
Goober
You at least have to add the Serializable attribute. What do you mean by 'manually serialize'? How else would you serialize?
Ronald Wildenberg