• C#对字典容器Dictionary<TKey, TValue>内容进行XML序列化或反序列化报错解决方法


    一、问题描述

            在使用C#对字典容器Dictionary内容进行XML序列化报错【System.Exception:“不支持类型 System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]],因为它实现 IDictionary。”】如下所示:

     

    反序列化操作时会报如下错误【System.Exception:“不支持类型 System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]],因为它实现 IDictionary。”】如下图所示

    二、问题分析

            通过异常信息可以看到是由于XML序列化或反序列化程序导致报错,且该错误是由于IDictionary导致,通过反编译查看【System.Xml.Serialization.TypeScope】内容可以发现代码直接对IDictionary类型直接做返回异常处理,不让序列化或反序列化。

    三、解决方法

    1、创建一个新的类【DictionaryEx】,继承Dictionary类和IXmlSerializable接口:

    1. using System.Collections.Generic;
    2. using System.Xml;
    3. using System.Xml.Schema;
    4. using System.Xml.Serialization;
    5. namespace Kernal
    6. {
    7. #region 可序列化字典类 + public class DictionaryEx
    8. ///
    9. /// 可序列化字典类
    10. ///
    11. /// 键泛型
    12. /// 值泛型
    13. [System.Serializable]
    14. public class DictionaryEx<TKey, TValue>
    15. : Dictionary<TKey, TValue>, IXmlSerializable
    16. {
    17. #region 构造函数
    18. #region 默认构造函数 + public DictionaryEx()
    19. ///
    20. /// 默认构造函数
    21. ///
    22. public DictionaryEx()
    23. : base()
    24. {
    25. }
    26. #endregion
    27. #region 构造函数 + public DictionaryEx(int capacity)
    28. ///
    29. /// 构造函数
    30. ///
    31. /// 可包含的初始元素数
    32. public DictionaryEx(int capacity)
    33. : base(capacity)
    34. {
    35. }
    36. #endregion
    37. #region 构造函数 + public DictionaryEx(IEqualityComparer comparer)
    38. ///
    39. /// 构造函数
    40. ///
    41. /// 比较键时要使用的 比较器 实现,或者为 null,以便为键类型使用默认的 比较器
    42. public DictionaryEx(IEqualityComparer comparer)
    43. : base(comparer)
    44. {
    45. }
    46. #endregion
    47. #region 构造函数 + public DictionaryEx(IDictionary dictionary)
    48. ///
    49. /// 构造函数
    50. ///
    51. /// 初始数据
    52. public DictionaryEx(IDictionary dictionary)
    53. : base(dictionary)
    54. {
    55. }
    56. #endregion
    57. #region 构造函数 + public DictionaryEx(int capacity, IEqualityComparer comparer)
    58. ///
    59. /// 构造函数
    60. ///
    61. /// 可包含的初始元素数
    62. /// 比较键时要使用的 比较器 实现,或者为 null,以便为键类型使用默认的 比较器
    63. public DictionaryEx(int capacity, IEqualityComparer comparer)
    64. : base(capacity, comparer)
    65. {
    66. }
    67. #endregion
    68. #region 构造函数 + public DictionaryEx(IDictionary dictionary, IEqualityComparer comparer)
    69. ///
    70. /// 构造函数
    71. ///
    72. /// 初始数据
    73. /// 比较键时要使用的 比较器 实现,或者为 null,以便为键类型使用默认的 比较器
    74. public DictionaryEx(IDictionary dictionary, IEqualityComparer comparer)
    75. : base(dictionary, comparer)
    76. {
    77. }
    78. #endregion
    79. #endregion
    80. #region 取得概要 + public XmlSchema GetSchema()
    81. ///
    82. /// 取得概要
    83. /// 注:根据MSDN的文档,此方法为保留方法,一定返回 null。
    84. ///
    85. /// Xml概要
    86. public XmlSchema GetSchema()
    87. {
    88. return null;
    89. }
    90. #endregion
    91. #region 从 XML 对象中反序列化生成本对象 + public void ReadXml(XmlReader reader)
    92. ///
    93. /// 从 XML 对象中反序列化生成本对象
    94. ///
    95. /// 包含反序列化对象的 XmlReader 流
    96. public void ReadXml(XmlReader reader)
    97. {
    98. XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
    99. XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
    100. bool wasEmpty = reader.IsEmptyElement;
    101. reader.Read();
    102. if (wasEmpty) return;
    103. while (reader.NodeType != XmlNodeType.EndElement)
    104. {
    105. reader.ReadStartElement("Item");
    106. reader.ReadStartElement("Key");
    107. TKey key = (TKey)keySerializer.Deserialize(reader);
    108. reader.ReadEndElement();
    109. reader.ReadStartElement("Value");
    110. TValue value = (TValue)valueSerializer.Deserialize(reader);
    111. reader.ReadEndElement();
    112. this.Add(key, value);
    113. reader.ReadEndElement();
    114. reader.MoveToContent();
    115. }
    116. reader.ReadEndElement();
    117. }
    118. #endregion
    119. #region 将本对象序列化为 XML 对象 + public void WriteXml(XmlWriter writer)
    120. ///
    121. /// 将本对象序列化为 XML 对象
    122. ///
    123. /// 待写入的 XmlWriter 对象
    124. public void WriteXml(XmlWriter writer)
    125. {
    126. XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
    127. XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
    128. foreach (TKey key in this.Keys)
    129. {
    130. writer.WriteStartElement("Item");
    131. writer.WriteStartElement("Key");
    132. keySerializer.Serialize(writer, key);
    133. writer.WriteEndElement();
    134. writer.WriteStartElement("Value");
    135. TValue value = this[key];
    136. valueSerializer.Serialize(writer, value);
    137. writer.WriteEndElement();
    138. writer.WriteEndElement();
    139. }
    140. }
    141. #endregion
    142. }
    143. #endregion
    144. }

      2、将原来使用Dictionary的类替换为DictionaryEx类

    1. ///
    2. /// 保存语言信息
    3. ///
    4. private bool SaveFileExpandNameList(DictionaryEx<string,string> languageInfoDic, string languageFilePathAndName)
    5. {
    6. bool success = false;
    7. if (languageInfoDic != null && languageInfoDic.Count >= 0)
    8. {
    9. //将对象序列化为xml字符串
    10. string strXml = XmlHelper.ObjectToXml2(languageInfoDic);
    11. if (!string.IsNullOrEmpty(strXml))
    12. {
    13. //先清空文件
    14. FileOPC.Clear(languageFilePathAndName);
    15. //保存Json字符串文件(覆盖写入)
    16. success = FileOPC.OverWrite(languageFilePathAndName, strXml);
    17. }
    18. }
    19. return success;
    20. }
    21. ///
    22. /// 获取语言信息
    23. ///
    24. /// 返回语言信息字典
    25. private DictionaryEx<string, string> GetLanguageInfo(string languageFilePathAndName)
    26. {
    27. if (string.IsNullOrEmpty(languageFilePathAndName)) return null;
    28. DictionaryEx<string, string> languageInfoDic = new DictionaryEx<string, string>();
    29. //读取xml文件字符串
    30. string strXml = FileOPC.Read(languageFilePathAndName);
    31. //读取xml文件并序列化为对象
    32. languageInfoDic = XmlHelper.XmlToObject2string, string>>(strXml);
    33. return languageInfoDic;
    34. }

    3、序列化DictionaryEx<TKey, TValue>容器内容的XML内容如下所示:

  • 相关阅读:
    你有了解过这些架构设计,架构知识体系吗?(架构书籍推荐)
    多目标优化算法:基于非支配排序的小龙虾优化算法(NSCOA)MATLAB
    Redis篇---第七篇
    nginx常用命令
    什么是向量嵌入?
    Field extension
    apache-atlas-hbase-hook源码分析
    BUG:ERROR: Could not find a version that satisfies the requirement cython
    Go语言知识查漏补缺|基本数据类型
    pthread_detach函数的应用
  • 原文地址:https://blog.csdn.net/xiaochenXIHUA/article/details/133716997