Существует ли сериализуемый общий класс пары ключ / значение in.NET?
Я ищу объект пары ключ / значение, который я могу включить в веб-службу.
Я пробовал использовать .NET System.Collections.Generic.KeyValuePair<>
класс, но он не правильно сериализуется в веб-службе. В веб-службе свойства ключа и значения не сериализуются, что делает этот класс бесполезным, если кто-то не знает способ исправить это.
есть ли другой универсальный класс, который может быть использован для этой ситуации?
Я бы использовал .NET System.Web.UI.Pair
класс, но он использует объект для своих типов. Было бы неплохо использовать универсальный класс, хотя бы для безопасности типов.
9 ответов:
просто определите структуру / класс.
[Serializable] public struct KeyValuePair<K,V> { public K Key {get;set;} public V Value {get;set;} }
Я не думаю, что есть как
Dictionary<>
сам по себе не является сериализуемым XML, когда мне нужно было отправить объект словаря через веб-службу, я закончил обертываниеDictionary<>
сам объект и добавление поддержки дляIXMLSerializable
./// <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 }
вы найдете причину, почему KeyValuePairs не могут быть сериализованы в этом сообщение в блоге MSDN
ответ структуры является самым простым решением, однако не единственным решением. "Лучшее" решение-написать пользовательский класс KeyValurPair, который является Сериализуемым.
[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; } }
в рамках 4.0 также есть добавление семейства кортежей классов, которые сериализуемы и равны. Вы можете использовать
Tuple.Create(a, b)
илиnew Tuple<T1, T2>(a, b)
.
KeyedCollection-это тип словаря, который может быть непосредственно сериализован в xml без каких-либо глупостей. Единственная проблема заключается в том, что вы должны получить доступ к значениям по: СОБР["ключ"].Значение;
XmlSerializer не работает со словарями. О, и у него тоже есть проблемы с KeyValuePairs
http://www.codeproject.com/Tips/314447/XmlSerializer-doesnt-work-with-Dictionaries-Oh-and
используйте DataContractSerializer, так как он может обрабатывать пару значений ключа.
public static string GetXMLStringFromDataContract(object contractEntity) { using (System.IO.MemoryStream writer = new System.IO.MemoryStream()) { var dataContractSerializer = new DataContractSerializer(contractEntity.GetType()); dataContractSerializer.WriteObject(writer, contractEntity); writer.Position = 0; var streamReader = new System.IO.StreamReader(writer); return streamReader.ReadToEnd(); } }
можно использовать
Tuple<string,object>
смотрите это для получения более подробной информации о
Tuple
использование : работа с кортежем в C# 4.0