C# .NET 中是否有可序列化的通用键/值对类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/83232/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 11:22:22  来源:igfitidea点击:

Is there a serializable generic Key/Value pair class in .NET?

提问by Dan Herbert

I'm looking for a key/value pair object that I can include in a web service.

我正在寻找可以包含在 Web 服务中的键/值对对象。

I tried using .NET's System.Collections.Generic.KeyValuePair<>class, but it does not properly serialize in a web service. In a web service, the Key and Value properties are not serialized, making this class useless, unless someone knows a way to fix this.

我尝试使用 .NET 的System.Collections.Generic.KeyValuePair<>类,但它没有在 Web 服务中正确序列化。在 Web 服务中,Key 和 Value 属性没有被序列化,这使得这个类毫无用处,除非有人知道解决这个问题的方法。

Is there any other generic class that can be used for this situation?

是否有任何其他通用类可用于这种情况?

I'd use .NET's System.Web.UI.Pairclass, but it uses Object for its types. It would be nice to use a Generic class, if only for type safety.

我会使用 .NET 的System.Web.UI.Pair类,但它的类型使用 Object。如果只是为了类型安全,最好使用 Generic 类。

采纳答案by leppie

Just define a struct/class.

只需定义一个结构/类。

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

回答by Compile This

I don't think there is as Dictionary<>itself isn't XML serializable, when I had need to send a dictionary object via a web service I ended up wrapping the Dictionary<>object myself and adding support for IXMLSerializable.

我不认为Dictionary<>它本身不是 XML 可序列化的,当我需要通过 Web 服务发送字典对象时,我最终自己包装了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
}

回答by Compile This

A KeyedCollection is a type of dictionary that can be directly serialized to xml without any nonsense. The only issue is that you have to access values by: coll["key"].Value;

KeyedCollection 是一种可以直接序列化为 xml 的字典,没有任何废话。唯一的问题是您必须通过以下方式访问值: coll["key"].Value;

回答by user56931

You will find the reason why KeyValuePairs cannot be serialised at this MSDN Blog Post

您将在此MSDN 博客文章中找到 KeyValuePairs 无法序列化的原因

The Struct answer is the simplest solution, however not the only solution. A "better" solution is to write a Custom KeyValurPair class which is Serializable.

Struct 答案是最简单的解决方案,但不是唯一的解决方案。“更好”的解决方案是编写一个可序列化的自定义 KeyValurPair 类。

回答by Peter Oehlert

In the 4.0 Framework, there is also the addition of the Tuple family of classes that are serializable and equatable. You can use Tuple.Create(a, b)or new Tuple<T1, T2>(a, b).

在 4.0 框架中,还添加了可序列化和可等同的 Tuple 系列类。您可以使用Tuple.Create(a, b)new Tuple<T1, T2>(a, b)

回答by Saraf Talukder

You can use Tuple<string,object>

您可以使用 Tuple<string,object>

see this for more details on Tupleusage : Working with Tuple in C# 4.0

有关Tuple用法的更多详细信息,请参阅此内容:在 C# 4.0 中使用元组

回答by GregoryBrad

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

    }

回答by Akodo_Shado

XmlSerializer doesn't work with Dictionaries. Oh, and it has problems with KeyValuePairs too

XmlSerializer 不适用于字典。哦,它也有 KeyValuePairs 的问题

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

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

回答by Hasse

Use the DataContractSerializer since it can handle the Key Value Pair.

使用 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();
        }
    }

回答by Teodor Tite

DataTableis my favorite collection for (solely) wrapping data to be serialized to JSON, since it's easy to expand without the need for an extra struct& acts like a serializable replacement for Tuple<>[]

DataTable是我最喜欢的用于(仅)包装要序列化为 JSON 的数据的集合,因为它很容易扩展而无需额外的struct& 就像一个可序列化的替代品Tuple<>[]

Maybe not the cleanest way, but I prefer to include & use it directly in the classes (which shall be serialized), instead of declaring a new struct

也许不是最干净的方式,但我更喜欢在类中直接包含和使用它(应该被序列化),而不是声明一个新的 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);
    }
}