it-swarm-eu.dev

Gibt es in .NET eine serialisierbare generische Schlüssel/Wert-Paarklasse?

Ich suche nach einem Schlüssel/Wert-Paar-Objekt, das ich in einen Web-Service aufnehmen kann.

Ich habe versucht, die .NET-Klasse System.Collections.Generic.KeyValuePair<> zu verwenden, aber sie wird in einem Web-Service nicht ordnungsgemäß serialisiert. In einem Webdienst werden die Key- und Value-Eigenschaften nicht serialisiert, sodass diese Klasse unbrauchbar wird, es sei denn, jemand weiß, wie dies behoben werden kann.

Gibt es eine andere generische Klasse, die für diese Situation verwendet werden kann?

Ich würde die System.Web.UI.Pair - Klasse von .NET verwenden, aber es verwendet Object für seine Typen. Es wäre schön, eine generische Klasse zu verwenden, wenn auch nur zur Typsicherheit.

74
Dan Herbert

Definieren Sie einfach eine struct/class.

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

Ich glaube nicht, dass Dictionary<> selbst nicht in XML serialisierbar ist. Als ich ein Wörterbuchobjekt über einen Webdienst senden musste, änderte ich das Dictionary<>-Objekt selbst und fügte Unterstützung für IXMLSerializable hinzu.

/// <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
}
22
Compile This

Sie finden den Grund, warum KeyValuePairs in diesem MSDN Blog Post nicht serialisiert werden kann.

Die Antwort von Struct ist die einfachste Lösung, jedoch nicht die einzige Lösung. Eine "bessere" Lösung ist das Schreiben einer benutzerdefinierten KeyValurPair-Klasse, die serialisierbar ist.

17
user56931
 [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; }

    }
5
GregoryBrad

Im 4.0 Framework gibt es außerdem die Tuple-Klasse von Klassen, die serialisierbar und gleichwertig sind. Sie können Tuple.Create(a, b) oder new Tuple<T1, T2>(a, b) verwenden.

1
Peter Oehlert

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();
        }
    }
0
Hasse

Eine KeyedCollection ist eine Art Wörterbuch, das ohne Unsinn direkt in xml serialisiert werden kann. Das einzige Problem ist, dass Sie auf folgende Werte zugreifen müssen: coll ["key"]. Value;

0
Will

DataTable ist meine Lieblingssammlung für das (ausschließliche) Serialisieren von Wrapping-Daten in JSON, da es leicht zu erweitern ist, ohne dass eine zusätzliche struct erforderlich ist und sich wie ein serialisierbarer Ersatz für Tuple<>[] verhält.

Vielleicht nicht der sauberste Weg, aber ich bevorzuge es, ihn direkt in die Klassen (die serialisiert werden sollen) aufzunehmen und zu verwenden, anstatt eine neue struct zu deklarieren

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);
    }
}
0
Teodor Tite

XmlSerializer funktioniert nicht mit Wörterbüchern. Oh, und es hat auch Probleme mit KeyValuePairs

http://www.codeproject.com/Tips/314447/XmlSerializer-doesnt-work-mit-Wörterbücher-Oh-und

0
Akodo_Shado