在C#(.NET Framework4.5.2)中如何(反)序列化含字符串数组值的可序列化字典?
解决C# .NET Framework 4.5.2中SerializableDictionary<string, string[]>的XML反序列化异常问题
我之前在处理带字典属性的XML序列化时也踩过类似的坑,你遇到的System.InvalidOperationException大概率是因为自定义的SerializableDictionary实现没有正确适配值为数组的场景,或者属性的XML特性配置不对。咱们一步步来解决:
1. 确保你的SerializableDictionary实现适配数组类型
很多网上流传的SerializableDictionary实现只处理了简单值类型,没有考虑值是数组的情况。你需要用支持IXmlSerializable且能正确读写数组的版本,比如下面这个实现:
using System; using System.Collections.Generic; using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable { public XmlSchema GetSchema() { return null; } 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("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(); } public void WriteXml(XmlWriter writer) { XmlSerializer keySerializer = new XmlSerializer(typeof(TKey)); XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue)); foreach (KeyValuePair<TKey, TValue> pair in this) { writer.WriteStartElement("Item"); writer.WriteStartElement("Key"); keySerializer.Serialize(writer, pair.Key); writer.WriteEndElement(); writer.WriteStartElement("Value"); valueSerializer.Serialize(writer, pair.Value); writer.WriteEndElement(); writer.WriteEndElement(); } } }
这个实现的核心是用XmlSerializer分别序列化键和值,不管值是数组还是其他复杂类型,都能正确处理。
2. 给包含字典的类属性添加正确的XML特性
在你的实体类中,给SerializableDictionary<string, string[]>类型的属性加上[XmlArray]和[XmlArrayItem]特性(或者直接用[XmlElement],不过前者更清晰):
using System.Xml.Serialization; [XmlRoot("MyConfig")] public class MyDataClass { // 这里指定数组元素的名称,让XML结构更清晰,也方便反序列化识别 [XmlArray("StringArrayDictionary")] [XmlArrayItem("DictionaryItem")] public SerializableDictionary<string, string[]> MyDictionary { get; set; } = new SerializableDictionary<string, string[]>(); }
3. 检查序列化和反序列化的代码
确保你的序列化/反序列化代码没有问题,比如:
序列化代码
var data = new MyDataClass(); data.MyDictionary.Add("Key1", new[] { "Value1", "Value2" }); data.MyDictionary.Add("Key2", new[] { "Value3" }); var serializer = new XmlSerializer(typeof(MyDataClass)); using (var writer = XmlWriter.Create("data.xml")) { serializer.Serialize(writer, data); }
反序列化代码
MyDataClass deserializedData; var serializer = new XmlSerializer(typeof(MyDataClass)); using (var reader = XmlReader.Create("data.xml")) { deserializedData = (MyDataClass)serializer.Deserialize(reader); }
注意:反序列化时一定要确保XmlSerializer的类型参数和序列化时的类型完全一致,不要漏掉泛型参数或者写错类型。
可能的异常原因排查
如果还是报错,你可以检查这几点:
- 之前的
SerializableDictionary实现中,ReadXml方法是否正确处理了数组的反序列化?比如有没有手动解析数组元素而不是用XmlSerializer,导致数组类型无法识别。 - 生成的XML文件结构是否正常?打开XML看看
<Value>节点下是不是正确生成了数组的元素,比如:<Value> <string>Value1</string> <string>Value2</string> </Value> - 有没有权限问题?比如反序列化时无法读取XML文件,不过这种情况一般会抛出
IOException,但也可能间接导致InvalidOperationException。
内容的提问来源于stack exchange,提问作者Knowledge Cube
相关产品推荐
相关产品推荐

