4

I have a generic class that implements Dictionary. I created a custom GetEnumerator that loops over the values instead of KeyValuePairs because I usually don't care about the keys. Here is a quick sample:

public class AssetHolder<T> : Dictionary<string, T>, IEnumerable, INotifyCollectionChanged, INotifyPropertyChanged where T : Asset
{
    // methods that don't relate to this post
    ...

    // enumeration methods
    IEnumerator System.Collections.IEnumerable.GetEnumerator() // this one is called by WPF objects like DataGrids
    {
        return base.Values.GetEnumerator();
    }
    new public IEnumerator<T> GetEnumerator() // this enumerator is called by the foreach command in c# code
    {
        return base.Values.GetEnumerator();
    }
}

I didn't add any data to my class (I only added methods), so in order to make it serializable, I added [DataContract] to the top of the class without any [DataMember] tags. I figured that this would simply use the base class's data for serialization/deserialization, but I got the following error:

Unable to cast object of type 'Enumerator[System.String,SignalEngineeringTestPlanner.Asset]' to type 'System.Collections.Generic.IEnumerator`1[System.Collections.Generic.KeyValuePair`2

I think this means that DataContractSerializer is calling the child's enumerator and it's getting confused because it expects a pair but it's getting an Asset object. Is there a way that I can (1) tell DataContractSerializer to use the base class's enumerator, or (2) create a special enumeration function and tell DataContractSerializer to use only that one?

hypehuman
  • 1,290
  • 2
  • 18
  • 37

2 Answers2

1

You can mark the type as Dictionary in your class instead of your derived class. The downside is that you will have to cast it (or have a separate reference with the correct type) when you're using it.

0

I managed to eleviate the errors that you were getting by implementing the INotifyCollectionChanged and INotifyPropertyChanged interfaces in the AssetHolder class:

[DataContract]
public class AssetHolder<T> : Dictionary<string, T>, IEnumerable, INotifyCollectionChanged, INotifyPropertyChanged where T : Asset 
{
    IEnumerator IEnumerable.GetEnumerator() // this one is called by WPF objects like DataGrids 
    {
        return base.Values.GetEnumerator();
    }
    new public IEnumerator<T> GetEnumerator() // this enumerator is called by the foreach command in c# code 
    {
        return base.Values.GetEnumerator();
    }

    event NotifyCollectionChangedEventHandler INotifyCollectionChanged.CollectionChanged
    {
        add { throw new NotImplementedException(); }
        remove { throw new NotImplementedException(); }
    }

    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
    {
        add { throw new NotImplementedException(); }
        remove { throw new NotImplementedException(); }
    }
}
Welton v3.62
  • 2,210
  • 7
  • 29
  • 46
  • Oops, sorry if I wasn't clear. The issue was not getting it to compile (I had already implemented those members). The issue was more to do with how DataContractSerializer sees the class. – hypehuman Mar 19 '12 at 21:24