Ich suche nach einem Schlüssel / Wert-Paar-Objekt, das ich in einen Webdienst aufnehmen kann.
Ich habe versucht, die .NET- System.Collections.Generic.KeyValuePair<>
Klasse zu verwenden, aber sie wird in einem Webdienst nicht ordnungsgemäß serialisiert. In einem Webdienst werden die Eigenschaften "Schlüssel" und "Wert" nicht serialisiert, wodurch diese Klasse unbrauchbar wird, es sei denn, jemand kennt eine Möglichkeit, dies zu beheben.
Gibt es eine andere generische Klasse, die für diese Situation verwendet werden kann?
Ich würde die .NET- System.Web.UI.Pair
Klasse verwenden, aber sie verwendet Object für ihre Typen. Es wäre schön, eine generische Klasse zu verwenden, wenn auch nur aus Gründen der Typensicherheit.
'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>>'
Ich glaube nicht, dass
Dictionary<>
XML an sich nicht serialisierbar ist. Als ich ein Wörterbuchobjekt über einen Webdienst senden musste, habe ich dasDictionary<>
Objekt selbst verpackt und Unterstützung für hinzugefügtIXMLSerializable
./// <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 }
quelle
Den Grund, warum KeyValuePairs nicht serialisiert werden können, finden Sie in diesem MSDN-Blogbeitrag
Die Strukturantwort ist die einfachste Lösung, jedoch nicht die einzige. Eine "bessere" Lösung besteht darin, eine benutzerdefinierte KeyValurPair-Klasse zu schreiben, die serialisierbar ist.
quelle
[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; } }
quelle
Im 4.0-Framework wurde außerdem die Tuple-Klassenfamilie hinzugefügt, die serialisierbar und gleichwertig ist. Sie können
Tuple.Create(a, b)
oder verwendennew Tuple<T1, T2>(a, b)
.quelle
Eine KeyedCollection ist eine Art Wörterbuch, das ohne Unsinn direkt in XML serialisiert werden kann. Das einzige Problem ist, dass Sie auf Werte zugreifen müssen, indem Sie: coll ["key"]. Value;
quelle
XmlSerializer funktioniert nicht mit Wörterbüchern. Oh, und es gibt auch Probleme mit KeyValuePairs
http://www.codeproject.com/Tips/314447/XmlSerializer-doesnt-work-with-Dictionaries-Oh-and
quelle
Verwenden Sie den DataContractSerializer, da er das Schlüsselwertpaar verarbeiten kann.
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(); } }
quelle
DataTable
ist meine Lieblingssammlung für (ausschließlich) Wrapping-Daten, die in JSON serialisiert werden sollen, da sie einfach erweitert werden können, ohne dass zusätzliche Funktionen erforderlich sind,struct
und sich wie ein serialisierbarer Ersatz für JSON verhaltenTuple<>[]
Vielleicht nicht der sauberste Weg, aber ich ziehe es vor, ihn direkt in die Klassen aufzunehmen und zu verwenden (die serialisiert werden sollen), anstatt einen neuen zu deklarieren
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); } }
quelle
Sie können verwenden
Tuple<string,object>
Weitere Informationen zur
Tuple
Verwendung finden Sie hier: Arbeiten mit Tupel in C # 4.0quelle