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

本文主要是介绍C#对字典容器Dictionary<TKey, TValue>内容进行XML序列化或反序列化报错解决方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、问题描述

        在使用C#对字典容器Dictionary<TKey, TValue>内容进行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<TKey, TValue>类和IXmlSerializable接口:

using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;namespace Kernal
{#region 可序列化字典类 + public class DictionaryEx<TKey, TValue>/// <summary>/// 可序列化字典类/// </summary>/// <typeparam name="TKey">键泛型</typeparam>/// <typeparam name="TValue">值泛型</typeparam>[System.Serializable]public class DictionaryEx<TKey, TValue>: Dictionary<TKey, TValue>, IXmlSerializable{#region 构造函数#region 默认构造函数 + public DictionaryEx()/// <summary>/// 默认构造函数/// </summary>public DictionaryEx(): base(){}#endregion#region 构造函数 + public DictionaryEx(int capacity)/// <summary>/// 构造函数/// </summary>/// <param name="capacity">可包含的初始元素数</param>public DictionaryEx(int capacity): base(capacity){}#endregion#region 构造函数 + public DictionaryEx(IEqualityComparer<TKey> comparer)/// <summary>/// 构造函数/// </summary>/// <param name="comparer">比较键时要使用的 比较器 实现,或者为 null,以便为键类型使用默认的 比较器</param>public DictionaryEx(IEqualityComparer<TKey> comparer): base(comparer){}#endregion#region 构造函数 + public DictionaryEx(IDictionary<TKey, TValue> dictionary)/// <summary>/// 构造函数/// </summary>/// <param name="dictionary">初始数据</param>public DictionaryEx(IDictionary<TKey, TValue> dictionary): base(dictionary){}#endregion#region 构造函数 + public DictionaryEx(int capacity, IEqualityComparer<TKey> comparer)/// <summary>/// 构造函数/// </summary>/// <param name="capacity">可包含的初始元素数</param>/// <param name="comparer">比较键时要使用的 比较器 实现,或者为 null,以便为键类型使用默认的 比较器</param>public DictionaryEx(int capacity, IEqualityComparer<TKey> comparer): base(capacity, comparer){}#endregion#region 构造函数 + public DictionaryEx(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)/// <summary>/// 构造函数/// </summary>/// <param name="dictionary">初始数据</param>/// <param name="comparer">比较键时要使用的 比较器 实现,或者为 null,以便为键类型使用默认的 比较器</param>public DictionaryEx(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer): base(dictionary, comparer){}#endregion#endregion#region 取得概要 + public XmlSchema GetSchema()/// <summary>/// 取得概要/// 注:根据MSDN的文档,此方法为保留方法,一定返回 null。/// </summary>/// <returns>Xml概要</returns>public XmlSchema GetSchema(){return null;}#endregion#region 从 XML 对象中反序列化生成本对象 + public void ReadXml(XmlReader reader)/// <summary>  /// 从 XML 对象中反序列化生成本对象/// </summary>  /// <param name="reader">包含反序列化对象的 XmlReader 流</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("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();}#endregion#region 将本对象序列化为 XML 对象 + public void WriteXml(XmlWriter writer)/// <summary>  /// 将本对象序列化为 XML 对象/// </summary>  /// <param name="writer">待写入的 XmlWriter 对象</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("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}#endregion
}

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

        /// <summary>/// 保存语言信息/// </summary>private bool SaveFileExpandNameList(DictionaryEx<string,string> languageInfoDic, string languageFilePathAndName){bool success = false;if (languageInfoDic != null && languageInfoDic.Count >= 0){//将对象序列化为xml字符串string strXml = XmlHelper.ObjectToXml2(languageInfoDic);if (!string.IsNullOrEmpty(strXml)){//先清空文件FileOPC.Clear(languageFilePathAndName);//保存Json字符串文件(覆盖写入)success = FileOPC.OverWrite(languageFilePathAndName, strXml);}}return success;}/// <summary>/// 获取语言信息/// </summary>/// <returns>返回语言信息字典</returns>private DictionaryEx<string, string> GetLanguageInfo(string languageFilePathAndName){if (string.IsNullOrEmpty(languageFilePathAndName)) return null;DictionaryEx<string, string> languageInfoDic = new DictionaryEx<string, string>();//读取xml文件字符串string strXml = FileOPC.Read(languageFilePathAndName);//读取xml文件并序列化为对象languageInfoDic = XmlHelper.XmlToObject2<DictionaryEx<string, string>>(strXml);return languageInfoDic;}

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

这篇关于C#对字典容器Dictionary<TKey, TValue>内容进行XML序列化或反序列化报错解决方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/181602

相关文章

SQL中如何添加数据(常见方法及示例)

《SQL中如何添加数据(常见方法及示例)》SQL全称为StructuredQueryLanguage,是一种用于管理关系数据库的标准编程语言,下面给大家介绍SQL中如何添加数据,感兴趣的朋友一起看看吧... 目录在mysql中,有多种方法可以添加数据。以下是一些常见的方法及其示例。1. 使用INSERT I

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

C#读写文本文件的多种方式详解

《C#读写文本文件的多种方式详解》这篇文章主要为大家详细介绍了C#中各种常用的文件读写方式,包括文本文件,二进制文件、CSV文件、JSON文件等,有需要的小伙伴可以参考一下... 目录一、文本文件读写1. 使用 File 类的静态方法2. 使用 StreamReader 和 StreamWriter二、二进

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

在Linux中改变echo输出颜色的实现方法

《在Linux中改变echo输出颜色的实现方法》在Linux系统的命令行环境下,为了使输出信息更加清晰、突出,便于用户快速识别和区分不同类型的信息,常常需要改变echo命令的输出颜色,所以本文给大家介... 目python录在linux中改变echo输出颜色的方法技术背景实现步骤使用ANSI转义码使用tpu

Conda与Python venv虚拟环境的区别与使用方法详解

《Conda与Pythonvenv虚拟环境的区别与使用方法详解》随着Python社区的成长,虚拟环境的概念和技术也在不断发展,:本文主要介绍Conda与Pythonvenv虚拟环境的区别与使用... 目录前言一、Conda 与 python venv 的核心区别1. Conda 的特点2. Python v

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

C#中Guid类使用小结

《C#中Guid类使用小结》本文主要介绍了C#中Guid类用于生成和操作128位的唯一标识符,用于数据库主键及分布式系统,支持通过NewGuid、Parse等方法生成,感兴趣的可以了解一下... 目录前言一、什么是 Guid二、生成 Guid1. 使用 Guid.NewGuid() 方法2. 从字符串创建

SQL Server配置管理器无法打开的四种解决方法

《SQLServer配置管理器无法打开的四种解决方法》本文总结了SQLServer配置管理器无法打开的四种解决方法,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录方法一:桌面图标进入方法二:运行窗口进入检查版本号对照表php方法三:查找文件路径方法四:检查 S