it-swarm-eu.dev

Existuje serializovatelný generický klíč/hodnota pár třídy v .NET?

Hledám objekt pár klíč/hodnota, který mohu zahrnout do webové služby.

Snažil jsem se použít třídu .NET System.Collections.Generic.KeyValuePair<> class, ale řádně se serializovat ve webové službě. Ve webové službě nejsou vlastnosti klíče a hodnoty serializovány, což činí tuto třídu zbytečnou, pokud někdo neví, jak to vyřešit.

Existuje nějaká jiná generická třída, která může být použita pro tuto situaci?

Použil bych .NET System.Web.UI.Pair class, ale pro své typy používá Object. Bylo by hezké používat třídu Generic, pouze pokud jde o typovou bezpečnost.

74
Dan Herbert

Stačí definovat struct/class.

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

Nemyslím si, že je Dictionary<> sám o sobě není XML serializovatelný, když jsem musel poslat objekt slovníku přes webovou službu, skončil jsem s balením Dictionary<> objektu a přidáním podpory pro 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
}
22
Compile This

Důvod, proč KeyValuePairs nemůže být serializován na tomto blogu příspěvku MSDN, naleznete zde

Strukturální odpověď je nejjednodušším řešením, nikoli však jediným řešením. "Lepším" řešením je zápis vlastní třídy KeyValurPair, která je Serializable.

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

V 4.0 Framework, tam je také přidání rodiny Tuple tříd, které jsou serializovatelné a vyrovnatelné. Můžete použít Tuple.Create(a, b) nebo new Tuple<T1, T2>(a, b).

1
Peter Oehlert

Použijte DataContractSerializer, protože může pracovat s párem klíčové hodnoty.

    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

KeyedCollection je typ slovníku, který lze přímo serializovat na xml bez jakéhokoliv nesmyslu. Jediným problémem je přístup k hodnotám pomocí: coll ["key"].

0
Will

DataTable je moje oblíbená kolekce pro (výhradně) zabalení dat, která mají být serializována do služby JSON, protože je snadné ji rozšířit bez nutnosti dodatečného struct & funguje jako serializovatelná náhrada Tuple<>[]

Možná nejde o nejčistší cestu, ale raději ji používám a používám přímo ve třídách (které budou serializovány) namísto deklarování nového 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);
    }
}
0
Teodor Tite

XmlSerializer nefunguje se slovníky. A má taky problémy s KeyValuePairs

http://www.codeproject.com/Tips/314447/XmlSerializer-doesnt-work-with-Dictionaries-Oh-and

0
Akodo_Shado