XmlSerializer序列化IDictionary出错的解决方法

翅膀的初衷

发表于2013-09-29 14:37:41

  最近在公司写API,为了方便调用,接口可以选择返回XML或者JSON二种类型,在使用c#中的XmlSerializer对字典对外象(Hashtable或Dictionary等)进行序列化时,会抛出异常(不支持类型 ***,因为它实现 IDictionary。).
搜索了一下,原来是IDictionary对象反射时Item属性存在重载(索引器是通过getItem取值的),导致无法正确取值!

  解决方法很简单,我们只要建新一个类型,派生自原类型并实现IXmlSerializable即可,以下分别以Hashtable与Dictionary<TKey,TValue>为例,演示如何解决访问题!

  Dictionary:

  

public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable { #region IXmlSerializable 成员 public System.Xml.Schema.XmlSchema GetSchema() { return null; } public void ReadXml(System.Xml.XmlReader reader) { XmlSerializer keySerializer = new XmlSerializer(typeof(TKey)); XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue)); bool isEmpty = reader.IsEmptyElement; reader.Read(); if (isEmpty) 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(); } public void WriteXml(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 }

  Hashtable:

  

public class SerializableHashtable : System.Collections.Hashtable, IXmlSerializable { #region IXmlSerializable 成员 public System.Xml.Schema.XmlSchema GetSchema() { return null; } private XmlSerializer serializer = new XmlSerializer(typeof(object)); public void ReadXml(System.Xml.XmlReader reader) { bool isEmpty = reader.IsEmptyElement; reader.Read(); if (isEmpty) return; while (reader.NodeType != System.Xml.XmlNodeType.EndElement) { reader.ReadStartElement("item"); reader.ReadStartElement("key"); object key = serializer.Deserialize(reader); reader.ReadEndElement(); reader.ReadStartElement("value"); object value = serializer.Deserialize(reader); reader.ReadEndElement(); this[key]= value; reader.ReadEndElement(); reader.MoveToContent(); } reader.ReadEndElement(); } public void WriteXml(System.Xml.XmlWriter writer) { foreach (object key in this.Keys) { writer.WriteStartElement("item"); writer.WriteStartElement("key"); serializer.Serialize(writer, key); writer.WriteEndElement(); writer.WriteStartElement("value"); object value = this[key]; serializer.Serialize(writer, value); writer.WriteEndElement(); writer.WriteEndElement(); } } #endregion }

  使用示例:

SerializableHashtable sh = new SerializableHashtable(); sh["ret"] = "0"; sh["msg"] = "序列化Hashtable测试"; XmlSerializer sr = new XmlSerializer(sh.GetType()); sr.Serialize(Response.Output, sh);

  输出XML:

<?xml version="1.0" encoding="utf-8"?> <SerializableHashtable> <item> <key> <string>msg</string> </key> <value> <string>序列化Hashtable测试</string> </value> </item> <item> <key> <string>ret</string> </key> <value> <string>0</string> </value> </item> </SerializableHashtable>