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

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

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

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

我尝试使用.NET的System.Collections.Generic.KeyValuePair<>类,但是它无法在Web服务中正确序列化。在Web服务中,键和值属性不会被序列化,从而使该类无用,除非有人知道解决此问题的方法。

在这种情况下还有其他通用类吗?

我将使用.NET的System.Web.UI.Pair类,但是它使用Object作为其类型。如果仅出于类型安全的考虑,最好使用Generic类。


只需定义一个结构体/类。

1
2
3
4
5
6
[Serializable]
public struct KeyValuePair<K,V>
{
  public K Key {get;set;}
  public V Value {get;set;}
}

我不认为这是因为Dictionary<>本身不是XML可序列化的,当我需要通过Web服务发送字典对象时,我最终自己包装了Dictionary<>对象并添加了对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/// <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
}

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

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 [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框架中,还添加了可序列化和等价的Tuple系列类。您可以使用Tuple.Create(a, b)new Tuple<T1, T2>(a, b)


DataTable是我最喜欢的用于(仅)包装要序列化为JSON的数据的集合,因为它很容易扩展,而无需额外的struct


使用DataContractSerializer,因为它可以处理键值对。

1
2
3
4
5
6
7
8
9
10
11
    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();
        }
    }

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

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


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


您可以使用Tuple<string,object>

有关Tuple用法的更多详细信息,请参见此:在C#4.0中使用Tuple。


推荐阅读