-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSerializableDictionary.cs
153 lines (123 loc) · 3.78 KB
/
SerializableDictionary.cs
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
143
144
145
146
147
148
149
150
151
152
153
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Xml.Serialization;
namespace SpecialFNs
{
[Serializable]
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue>
: Dictionary<TKey, TValue>, IXmlSerializable
{
public SerializableDictionary()
{
}
// Support for [Serializable]
public SerializableDictionary(SerializationInfo a_Info, StreamingContext a_Context) : base(a_Info, a_Context)
{
}
#region XML Serialization rules
private void ReadXml_Simple(System.Xml.XmlReader reader)
{
bool hasItem = reader.ReadToDescendant("item");
if (!hasItem)
{
reader.Skip();
return;
}
for (; hasItem; hasItem = reader.ReadToNextSibling("item"))
{
TKey key = (TKey)Convert.ChangeType(reader.GetAttribute("key"), typeof(TKey));
TValue value = (TValue)Convert.ChangeType(reader.GetAttribute("value"), typeof(TValue));
this.Add(key, value);
}
reader.ReadEndElement();
}
private void WriteXml_Simple(System.Xml.XmlWriter writer)
{
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartAttribute("key");
writer.WriteValue(key.ToString());
writer.WriteEndAttribute();
writer.WriteStartAttribute("value");
TValue value = this[key];
writer.WriteValue(value.ToString());
writer.WriteEndAttribute();
writer.WriteEndElement();
}
}
private void ReadXml_Complex(System.Xml.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 != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
private void WriteXml_Complex(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
#endregion
bool CanUseSimpleFormat()
{
var typeConvK = System.ComponentModel.TypeDescriptor.GetConverter(typeof(TKey));
if (!typeConvK.CanConvertFrom(typeof(String)) || !typeConvK.CanConvertTo(typeof(String)))
return false;
var typeConvV = System.ComponentModel.TypeDescriptor.GetConverter(typeof(TValue));
if (!typeConvV.CanConvertFrom(typeof(String)) || !typeConvV.CanConvertTo(typeof(String)))
return false;
return true;
}
#region IXmlSerializable Members
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
{
return null;
}
void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
{
if (CanUseSimpleFormat())
ReadXml_Simple(reader);
else
ReadXml_Complex(reader);
}
void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
{
if (CanUseSimpleFormat())
WriteXml_Simple(writer);
else
WriteXml_Complex(writer);
}
#endregion
}
}