2008-09-17 19 views
73

我正在尋找可以包含在Web服務中的鍵/值對對象。.NET中是否有可序列化的通用鍵/值對類?

我嘗試使用.NET的System.Collections.Generic.KeyValuePair<>類,但它沒有在Web服務中正確序列化。在Web服務中,Key和Value屬性沒有被序列化,這使得這個類沒用,除非有人知道解決這個問題的方法。

有沒有其他的泛型類可以用於這種情況?

我會使用.NET的System.Web.UI.Pair類,但它使用Object作爲它的類型。如果僅用於類型安全,那麼使用通用類將會很好。

回答

87

只需定義一個結構/類。

[Serializable] 
public struct KeyValuePair<K,V> 
{ 
    public K Key {get;set;} 
    public V Value {get;set;} 
} 
+5

簡單。當你停下來想想... – Paddy 2012-03-15 11:52:52

+3

@Paddy:知道值類型如何被散列和比較平等是必須 – leppie 2012-03-15 11:56:49

+2

的IDictionary現在是序列化,在4.5(至少JSON) – tomg 2013-05-23 09:50:20

20

我不認爲這是因爲Dictionary<>本身不是XML序列化的,當我有需要通過Web服務,我結束了包裹Dictionary<>對象自己並添加IXMLSerializable Support向用戶發送一個字典對象。

/// <summary> 
/// Represents an XML serializable collection of keys and values. 
/// </summary> 
/// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> 
/// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> 
[XmlRoot("dictionary")] 
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable 
{ 
    #region Constants 

    /// <summary> 
    /// The default XML tag name for an item. 
    /// </summary> 
    private const string DEFAULT_ITEM_TAG = "Item"; 

    /// <summary> 
    /// The default XML tag name for a key. 
    /// </summary> 
    private const string DEFAULT_KEY_TAG = "Key"; 

    /// <summary> 
    /// The default XML tag name for a value. 
    /// </summary> 
    private const string DEFAULT_VALUE_TAG = "Value"; 

    #endregion 

    #region Protected Properties 

    /// <summary> 
    /// Gets the XML tag name for an item. 
    /// </summary> 
    protected virtual string ItemTagName 
    { 
     get 
     { 
      return DEFAULT_ITEM_TAG; 
     } 
    } 

    /// <summary> 
    /// Gets the XML tag name for a key. 
    /// </summary> 
    protected virtual string KeyTagName 
    { 
     get 
     { 
      return DEFAULT_KEY_TAG; 
     } 
    } 

    /// <summary> 
    /// Gets the XML tag name for a value. 
    /// </summary> 
    protected virtual string ValueTagName 
    { 
     get 
     { 
      return DEFAULT_VALUE_TAG; 
     } 
    } 

    #endregion 

    #region Public Methods 

    /// <summary> 
    /// Gets the XML schema for the XML serialization. 
    /// </summary> 
    /// <returns>An XML schema for the serialized object.</returns> 
    public XmlSchema GetSchema() 
    { 
     return null; 
    } 

    /// <summary> 
    /// Deserializes the object from XML. 
    /// </summary> 
    /// <param name="reader">The XML representation of the object.</param> 
    public void ReadXml(XmlReader reader) 
    { 
     XmlSerializer keySerializer = new XmlSerializer(typeof(TKey)); 
     XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue)); 

     bool wasEmpty = reader.IsEmptyElement; 

     reader.Read(); 

     if (wasEmpty) 
     { 
      return; 
     } 

     while (reader.NodeType != XmlNodeType.EndElement) 
     { 
      reader.ReadStartElement(ItemTagName); 

      reader.ReadStartElement(KeyTagName); 
      TKey key = (TKey)keySerializer.Deserialize(reader); 
      reader.ReadEndElement(); 

      reader.ReadStartElement(ValueTagName); 
      TValue value = (TValue)valueSerializer.Deserialize(reader); 
      reader.ReadEndElement(); 

      this.Add(key, value); 

      reader.ReadEndElement(); 
      reader.MoveToContent(); 
     } 

     reader.ReadEndElement(); 
    } 

    /// <summary> 
    /// Serializes this instance to XML. 
    /// </summary> 
    /// <param name="writer">The writer to serialize to.</param> 
    public void WriteXml(XmlWriter writer) 
    { 
     XmlSerializer keySerializer = new XmlSerializer(typeof(TKey)); 
     XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue)); 

     foreach (TKey key in this.Keys) 
     { 
      writer.WriteStartElement(ItemTagName); 

      writer.WriteStartElement(KeyTagName); 
      keySerializer.Serialize(writer, key); 
      writer.WriteEndElement(); 

      writer.WriteStartElement(ValueTagName); 
      TValue value = this[key]; 
      valueSerializer.Serialize(writer, value); 
      writer.WriteEndElement(); 

      writer.WriteEndElement(); 
     } 
    } 

    #endregion 
} 
0

KeyedCollection是一種字典類型,可以直接序列化爲xml而不會有任何廢話。唯一的問題是您必須通過以下方式訪問值:coll [「key」]。Value;

16

你會發現爲什麼KeyValuePairs不能在這個MSDN Blog Post

該結構的答案被序列化的原因是最簡單的解決方案,但不是唯一的解決辦法。 「更好的」解決方案是編寫一個可序列化的Custom KeyValurPair類。

1

在4.0框架中,還增加了可序列化和可等化的Tuple族類。您可以使用Tuple.Create(a, b)new Tuple<T1, T2>(a, b)

5
[Serializable] 
public class SerializableKeyValuePair<TKey, TValue> 
    { 

     public SerializableKeyValuePair() 
     { 
     } 

     public SerializableKeyValuePair(TKey key, TValue value) 
     { 
      Key = key; 
      Value = value; 
     } 

     public TKey Key { get; set; } 
     public TValue Value { get; set; } 

    } 
相關問題