tags:

views:

40

answers:

2

EDIT

  • Ok, I've got it, it's not serializable.........so, how do I go about serializing it?

Scenario

  1. I have a custom BindableDictionary that I use to bind with a grid control for automatically updating the grid when the underlying datasource changes.
  2. I now want to extend my application to use WCF, so that when the server-side has finished updating the BindableDictionary with new values, it can pass this dictionary to the client, which in turn can perform the update on the Client GUI.

Problem

  • How do I go about sending this custom BindableDictionary over the wire?
  • What is the best way to implement this?
  • The reason I ask about an implementation method is that every example I've seen of Duplex, Callbacks or the Observer Pattern for "PUSHING" my data to the client, only uses an example of passing strings, and it's very primitive - Whenever I update the examples to use my custom BindableDictionary, I cannot get it to work.
  • Am I missing something?

BindableDictionary

    public class BindableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IBindingList
    {
        private Dictionary<TKey, TValue> source = new Dictionary<TKey, TValue>();

        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 { throw new NotImplementedException(); } 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);

            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: 

If you have a specific set of key/values for your BindableDictionary, you could set up your own "data-transfer" object that reflects those values:

[DataContract]
public class MyDTOType
{
   [DataMember]   
   public (keytype) Key { get; set; }
   [DataMember]   
   public (valuetype) Value { get; set; }
}

and then have a DTO object that contains a List<MyDTOType>:

[DataContract]
public class MyDTOList
{
   [DataMember]   
   public List<MyDTOType> ListOfKeyValues { get; set; }
}

Now, as long as you have serializable types for the (keytype) and the (valuetype) in your MyDTOType class, this will be able to travel across the wire in WCF:

[ServiceContract]
interface IMyService
{
    [OperationContract]
    public MyDTOList GetAllValues(int someCriteria);
}

and the last step you need to find a way to handle nicely is converting your BindableDictionary<TKey, TValue) to a MyDTOList that contains a list of MyDTOType instances that contain a key of TKey type and a value of TValue type. You could probably use something like AutoMapper to handle this conversion on an item-by-item basis.

marc_s
A: 

The answer was that the dictionary was not serializable. I have designed a serializable dictionary now that works.

Goober