如何告诉DataContract使用基类的GetEnumerator?

时间:2012-03-19 20:59:54

标签: c# serialization foreach datacontract enumerator

我有一个实现Dictionary的泛型类。我创建了一个自定义的GetEnumerator,它循环使用值而不是KeyValuePairs,因为我通常不关心键。这是一个快速示例:

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();
    }
}

我没有向我的类中添加任何数据(我只添加了方法),所以为了使其可序列化,我将[DataContract]添加到了类的顶部而没有任何[DataMember]标记。我认为这只会使用基类的数据进行序列化/反序列化,但是我收到了以下错误:

无法投射类型&#39; Enumerator [System.String,SignalEngineeringTestPlanner.Asset]&#39;输入&#39; System.Collections.Generic.IEnumerator`1 [System.Collections.Generic.KeyValuePair`2

我认为这意味着DataContractSerializer正在调用孩子的枚举器,并且它会让人感到困惑,因为它需要一对,但它会获得一个Asset对象。有没有办法可以(1)告诉DataContractSerializer使用基类的枚举器,或者(2)创建一个特殊的枚举函数并告诉DataContractSerializer只使用那个?

2 个答案:

答案 0 :(得分:1)

您可以在类中将类型标记为Dictionary,而不是派生类。缺点是当你使用它时,你必须使用它来投射它(或者使用正确类型的单独引用)。

答案 1 :(得分:0)

我设法通过在AssetHolder类中实现INotifyCollectionChanged和INotifyPropertyChanged接口来缓解您所获得的错误:

[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(); }
    }
}