2008-09-17 9 views
73

私は、Webサービスに含めることができるキー/値のペアオブジェクトを探しています。.NETにシリアル化可能な汎用キー/値ペアクラスがありますか?

.NETのSystem.Collections.Generic.KeyValuePair<>クラスを使用しようとしましたが、Webサービスで正しくシリアル化されません。 Webサービスでは、キーと値のプロパティはシリアル化されていないため、誰かがこれを修正する方法を知らない限り、このクラスは役に立たなくなります。

このような状況で使用できる他の汎用クラスはありますか?

.NETのSystem.Web.UI.Pairクラスを使用しますが、その型にObjectを使用します。タイプセーフティの場合にのみGenericクラスを使用するとよいでしょう。

答えて

87

struct/classを定義するだけです。

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

シンプルKeyValuePairsに問題があります。あなたが停止し、それについて考えているとき... – Paddy

+3

@Paddy:valuetypeがハッシュ化され、等価性を比較する方法を知っている必要があります – leppie

+2

IDictionaryは4.5で(少なくともJSONで)シリアライザブルです – tomg

20

私はDictionary<>オブジェクトを自分で包むとIXMLSerializableのサポートを追加してしまったウェブサービスを介して辞書オブジェクトを送信する必要が持っていたとき、私は、XMLシリアル化可能ではありません自体Dictionary<>として存在しているとは思いません。

/// <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 
} 
+5

OPには全く辞書がありません。 –

0

KeyedCollectionはナンセンスなしでxmlに直接シリアル化できる辞書の一種です。唯一の問題は、以下のように値にアクセスする必要があるということです:coll ["key"]。

+0

公開されているコンストラクタがないため、KeyedCollectionを** WebService **内で直列化することはできません。[Serializable]属性はリモート処理でのみ機能します。 – Martin

16

あなたはKeyValuePairsは、構造体の答えは、最も簡単な解決策は、しかしない唯一のソリューションです。このMSDN Blog Post

でシリアライズすることができない理由があります。 「より良い」解決策は、SerializableであるカスタムKeyValurPairクラスを書くことです。

+9

DataContractSerializer(.NET 3.0およびWCFに付属)は、KeyValuePair 01を完全に処理できることに注意してください。したがって、一般的なシリアル化の問題ではなく、使用する特定のシリアライザの問題です(MSDNページへのリンクが示すように)。 –

1

4.0フレームワークには、シリアライズ可能で同等のクラスのTupleファミリが追加されています。 Tuple.Create(a, b)またはnew Tuple<T1, T2>(a, b)を使用できます。

+16

タプル型はシリアライズ可能ですが、残念ながらXMLシリアライズ可能ではありません – Cheetah

-3

あなたはTuple使用方法の詳細については、これを見るTuple<string,object>

を使用することができます。Working with Tuple in C# 4.0

+15

これは既に提案されています(http://stackoverflow.com/questions/83232/is-there-a-serializable-generic-key-value-pair-クラスイン・ネット/ 4598558#4598558)。残念ながら、TupleクラスはXML Serializableではありません。 –

+0

ありがとうDan Herbert –

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

    } 
関連する問題