2010-07-23 98 views
1

我发现自己经常面临这个问题:我有一个字典,其中的关键是一些简单的数字ID和值是一个对象。该ID也包含在该值对象的特定属性中。字典<K,V>实现IList <V>

然后,我希望能够反序列化一些(格式不灵活),XML,看起来像:

<listitem> 
    <id>20359</id> 
    <someotherval>foo</someotherval> 
</listitem> 
<listitem> 
    ... 

这需要我用List<V>反序列化,这是不方便,要手动将其转换成一个Dictionary<K,V>

第二个问题是绑定。绑定列表要求源实现ICollection(如果我没有记错的话),并且再次手动创建新的List<V>并从Dictionary<K,V>填充它是一件很痛苦的事情。

我现在,相当难看但实用的解决方案是有以下类:

public abstract class Keyed<KeyType> 
{ 
public KeyType key { get; set; } 
} 

public class KeyedDictionary<KeyType, ValueType> : 
Dictionary<KeyType, ValueType> 
where ValueType : Keyed<KeyType> 
{ 
// ... 
} 

public class KeyedList<KeyType, ValueType> : 
IList<ValueType>, 
System.Collections.IList 
where ValueType : Keyed<KeyType> 
{ 
public readonly KeyedDictionary<KeyType, ValueType> dict = 
    new KeyedDictionary<KeyType, ValueType>(); 

// ... 
} 

这工作,但它的内部大和丑陋。有没有更好的方法?


编辑:这是我解决的解决方案。

public interface IKeyed<KeyType> 
{ 
    KeyType Key { get; } 
} 

public class KeyedList<KeyType, ValueType> : 
    KeyedCollection<KeyType, ValueType> 
    where ValueType : IKeyed<KeyType> 
{ 
    protected override KeyType GetKeyForItem(ValueType item) { return item.Key; } 
} 
+0

这对我来说确实很不错。它符合要求,它是直接的泛型和接口,没有tomfoolery。 – 2010-07-24 00:00:36

+0

除非你的问题是关于C#编程语言,否则请保留“C#”。这个问题是关于.NET,而不是关于C#。 C#就是您正在编写的语言,以便您可以使用.NET。 – 2010-07-24 01:37:33

回答

3

这听起来像内置的KeyedCollection<K,I>类型可能会伎俩。这是一个抽象类,因此您需要派生自己的具体子类,但这很容易。

您可以根据您的确切需求创建单独的专用实现,也可以创建一个接受键选择器委托作为构造函数参数的单个通用版本。 (在通用版本将略高于专门的版本不太有效,因为每个有一个键查找时间委托调用的成本。)

var myKeyedByIdCollection = 
    new ProjectionKeyedCollection<int, MyCustomType>(i => i.Id); 

// ... 

public class ProjectionKeyedCollection<TKey, TItem> 
    : KeyedCollection<TKey, TItem> 
{ 
    private readonly Func<TItem, TKey> _keySelector; 

    public ProjectionKeyedCollection(Func<TItem, TKey> keySelector) 
    { 
     if (keySelector == null) 
      throw new ArgumentNullException("keySelector"); 

     _keySelector = keySelector; 
    } 

    protected override TKey GetKeyForItem(TItem item) 
    { 
     return _keySelector(item); 
    } 
} 
+1

好的答案,除了一件事:这个泛型集合可以序列化为XML,但不是反序列化的,因为它没有无参数的构造函数。有两种方法可以解决这个问题:1.将集合包装在初始化它的类中; 2.派生一个提供无参数构造函数的类的专门版本 – 2010-07-24 00:46:00

+0

谢谢!我希望我在一年前知道KeyedCollection!我将在问题中粘贴我的实现。 – Reinderien 2010-07-24 14:12:40

0

什么只是反序列化到List<something>,然后用.ToDictionary()那个清单?这看起来不太方便。

+0

这是不理想的,因为然后在字典上的任何操作后,我不得不做相反的.ToList()为了做绑定或序列化。理想情况下,不必保持字典和列表同步,它们将是同一个对象。 – Reinderien 2010-07-24 02:15:21

相关问题