Я ищу объект пары ключ / значение, который можно включить в веб-службу.
Я пробовал использовать System.Collections.Generic.KeyValuePair<>
класс .NET , но он не сериализуется должным образом в веб-службе. В веб-службе свойства Key и Value не сериализуются, что делает этот класс бесполезным, если кто-то не знает способ исправить это.
Есть ли другой общий класс, который можно использовать в этой ситуации?
Я бы использовал System.Web.UI.Pair
класс .NET , но он использует Object для своих типов. Было бы неплохо использовать Generic класс, хотя бы для обеспечения безопасности типов.
'AttributeCollection' does not contain a definition for 'Where' and the best extension method overload 'Queryable.Where<KeyValuePair<string, object>>(IQueryable<KeyValuePair<string, object>>, Expression<Func<KeyValuePair<string, object>, bool>>)' requires a receiver of type 'IQueryable<KeyValuePair<string, object>>'
Я не думаю, что существует, поскольку
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.
Ответ Struct - это самое простое, но не единственное решение. «Лучшее» решение - написать класс Custom 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 Framework также добавлено семейство классов Tuple, которые можно сериализовать и уравнять. Вы можете использовать
Tuple.Create(a, b)
илиnew Tuple<T1, T2>(a, b)
.источник
KeyedCollection - это тип словаря, который можно напрямую сериализовать в xml без всякой ерунды. Единственная проблема в том, что вам нужно получить доступ к значениям с помощью: coll ["key"]. Value;
источник
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(); } }
источник
DataTable
- моя любимая коллекция для (исключительно) упаковки данных, которые будут сериализованы в JSON, поскольку ее легко расширять без необходимости в дополнительныхstruct
и действует как сериализуемая замена дляTuple<>[]
Возможно, это не самый чистый способ, но я предпочитаю включать и использовать его непосредственно в классах (которые должны быть сериализованы), вместо того, чтобы объявлять новый
struct
class AnyClassToBeSerialized { public DataTable KeyValuePairs { get; } public AnyClassToBeSerialized { KeyValuePairs = new DataTable(); KeyValuePairs.Columns.Add("Key", typeof(string)); KeyValuePairs.Columns.Add("Value", typeof(string)); } public void AddEntry(string key, string value) { DataRow row = KeyValuePairs.NewRow(); row["Key"] = key; // "Key" & "Value" used only for example row["Value"] = value; KeyValuePairs.Rows.Add(row); } }
источник
Вы можете использовать
Tuple<string,object>
см. здесь для получения дополнительных сведений об
Tuple
использовании: Работа с кортежем в C # 4.0источник