创建一个可以序列化的Dictionary类

最近在调试项目的发现了一个错误,错误提示如下

反射类型“StockImageManage.Setting”时出错。

{"无法序列化 System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[MP_ZDImageCheck_CS.TypePageCount, MP_ZDImageCheck_CS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] 类型的成员 MP_ZDImageCheck_CS.BusinessParameter.TypePageCounts,因为它实现 IDictionary。"}

后来发现是StockImageManage.Setting里面包含一个Dictionary类型的属性,而Dictionary是无法序列化的,为了解决这个问题,于是就自己写了一个可以序列化的类SerializableDictionary。具体内容如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace MP_ZDImageCheck_CS
{

    //说明:开始时准备设计成SerializableDictionary<U, T>,后来发现在多数情况下的key只需要是字符串就足够了,所以就不理会U的类型,直接使用默认的string了。
    public class SerializableDictionary<T> :
        Dictionary<string, T>, //继承Dictionary
        System.Xml.Serialization.IXmlSerializable //要能够序列化,必须实现IXmlSerializable接口 
    {
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            throw new NotImplementedException();
        }

 

        //从xml文件中读取内容并转换为对象

        public void ReadXml(System.Xml.XmlReader reader)
        {
            if (reader.IsEmptyElement)
                return;

            Type type = typeof(T);
            PropertyInfo[] pis = type.GetProperties(); //获取类型T中的所有属性信息

            reader.Read();
            while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
            {
                //当前节点的限定名。例如,对于元素 <bk:book>,Name 为 bk:book。
                string key = reader.Name;

 

                //调用类型的默认构造函数创建类型T的实例,并作为value值写入Dictionary对象中
                this[key] = (T)type.GetConstructor(new Type[] { }).Invoke(null);
                if (!reader.IsEmptyElement)
                {
                    reader.ReadStartElement();
                    if (reader.NodeType != System.Xml.XmlNodeType.EndElement)
                    {
                        foreach (PropertyInfo pi in pis)
                        {
                            pi.SetValue(this[key],
                                //根据属性的类型对读取出来的字符串进行转换
                                Convert.ChangeType(reader.ReadElementString(pi.Name), pi.PropertyType), null);
                        }
                    }
                }
                reader.Read();
            }
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            Type type = typeof(T);
            //获取对象的全部属性信息
            PropertyInfo[] pis = type.GetProperties();
            foreach (string key in this.Keys)
            {
                writer.WriteStartElement(key);

                //将对象的每一个属性名和属性值写入xml文件中
                foreach (PropertyInfo pi in pis)
                {
                    //<属性名>属性值</属性名>
                    //<pi.Name>pi.GetValue(this[key], null).ToString()</pi.Name>
                    writer.WriteElementString(pi.Name, pi.GetValue(this[key], null).ToString());
                }
                writer.WriteEndElement();
            }
        }
    }
}

调用方式如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace SerializeDemo
{

    public class Student
    {
        public string Code { get; set; }
        public int Age { get; set; }
        public string Name { get; set; }
    }


    public class School
    {
        public SerializableDictionary<Student> stuSettings { get; set; }
    }

   

    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            p.MyReadTest();
            Console.Read();
        }

        void MyReadTest()
        {
            School school = new School();
            XmlSerializer xs = new XmlSerializer(typeof(School));
            FileStream fs = new FileStream(@"d:\mytest.xml", FileMode.Open);
            school = (School)xs.Deserialize(fs);
        }
      
        void MyWriteTest()
        {
            School school = new School();
            school.stuSettings = new SerializableDictionary<Student>();
            school.stuSettings ["a01"] = new Student() { Age = 18, Name = "QQ", Code = "a01" };
            school.stuSettings ["a02"] = new Student() { Age = 81, Name = "FF", Code = "a02" };
            school.stuSettings ["b01"] = new Student() { Age = 58, Name = "DD", Code = "b01" };
            school.stuSettings ["b02"] = new Student() { Age = 7, Name = "MN", Code = "b02" };

            XmlSerializer xs = new XmlSerializer(typeof(School));
            FileStream fs = new FileStream(@"d:\mytest.xml", FileMode.Create);
            xs.Serialize(fs, school);
            fs.Close();
        }

    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
对数据库设计教学的感想 摘要:该文强调了在信息化社会中,信息技术在各个方面都处于非常重要的位置。 而对于数据库技术又是信息处理技术中最核心的支撑技术。所以数据库技术已经渗透到 社会的各个方面,对于数据库的学习就非常重要。对于数据库教学中,难点在于数据库 的设计。该文强调了数据库的概念模型设计阶段的步骤。 关键词:信息技术 数据库 E-R图 在信息化社会发展过程中,信息技术是经济、社会、军事、航天等领域中最重要的 技术之一,而数据库技术则是信息处理技术中最核心的支撑技术。在日常的社会和经济 活动中,数据库技术又是使用最普遍的一门技术,诸如办公自动化系统、企业资源计划 、决策支持系统、电子商务系统、证券交易系统、银行信息系统等大量管理信息系统, 都离不开数据库技术。数据库技术已经渗透到社会的方方面面,所以对于数据库的学习 就显得尤为重要。 数据库在软件技术专业中,是一门很重要的专业课程,学生对操作型的章节掌握起 来还比较容易。但对理论部分掌握起来就比较难。特别对于实体- 关系图以及规范化的设计,学生学起来都会比较吃力。 因此我总结了这几年中教授数据库的经验,对数据库的设计简单进行一下汇总。 1 需求分析阶段 在讲解实体- 关系图的设计阶段,首先是先弄清楚任务的描述,业务的流程。用数据流图表达数据和 处理过程的关系。系统中的数据则借助数据字典(Data Dictionary,简称DD)来描述。数据字典是各数据描述的集合,它是关于数据库中数 据的描述,即元数据,而不是数据本身。数据字典至少应该包含每个字段的数据型和 在每个表内的主外键。下面给出一个简单的数据字典的例子(如表1): Fk=foreign key (外键) Pk=primary key (主键) 2 概念结构设计阶段 通过对任务需求进行综合、归纳与抽象,形成一个独立于具体DBMS的概念模型,可 以用E-R图表示。 创建E-R图的步骤如下: (1)熟悉需求 这个阶段的任务是从目的描述和范围描述开始,收集源材料,制定约束和规范。在 实际教学中收集源材料是这阶段的重点。在这个阶段要仔细分析任务的描述,业务的流 程。形成基本数据资料表。例如:要创建一个图书馆图书借阅的管理系统,系统要求跟 踪记录借阅者借阅图书的情况,通过该系统可以查阅某一位同学借书的情况,同时可以 根据作者查找某一本书。要实现这样的功能首先要对图书馆的工作流程非常清楚。把工 作流程形成基本数据。 (2)定义实体 实体集成员都有一个共同的特征和属性集,可以从收集的源材料——基本数据资料表 中直接或间接标识出大部分实体。根据源材料名字表中表示物的术语中将其名词部分代 表的实体标识出来,从而初步找出潜在的实体,形成初步实体表。拿图书管理系统作例 子:在任务描述中会给出似于一个借阅者一次可以借阅多本书、每次可以借阅多长时 间、一本书可以由若干个作者写、一个作者可以写若干本书等这样的信息。通过这些信 息就可以初步的得出有书、作者、借阅者这几个实体。形成初步的实体表。 (3)定义关系 根据实际的业务需求和规则,使用实体联系矩阵来标识实体间的二元关系,然后根 据实际情况确定出连接关系的势、关系名和说明,确定关系型。通过确定关系型, 分析是否为m:n关系,如果是则再增加一个实体,变成两个1:m的关系。在图书管理系 统分析出的实体:作者和书籍。通过上面的分析可知,一个作者可以写若干本书、同时 一本书也可能由若干个作者。所以作者和书籍之间是一种多对多的关系。所以应增加一 个实体解决多对多的关系。具体见后面的图示。 (4)定义主键 从确定的实体中确定候选码,以便唯一识别每个实体的实例,再从侯选码中确定主 键。为了确定主键和关系的有效性,通过非空规则和非多值规则来保证,即一个实体实 例的一个属性不能是空值,也不能在同一个时刻有一个以上的值。即是实体完整性约束 。还是利用图书馆借阅系统作例子:在这个系统中分析出有作者和书籍这两个实体。但 这两个实体是多对多的关系。即一个作者可以写若干本书,一本书有可能由若干作者来 写。通过第三步的分析需增加一个实体。所以这三个实体的主键分别为作者(作者编号 )书籍(书籍编号)另一个实体的主键是(作者编号,书籍编号)。 (5)定义属性 从源数据表中抽取说明性的名词开发出属性表,确定属性的所有者。定义非主码属 性,检查属性的非空及非多值规则。此外,还要检查完全依赖函数规则和非传递依赖规 则,保证一个非主码属性必须依赖于主码、整个主码、仅仅是主码。以此得到了至少符 合关系理论第三范式的全属性视图。例如在图书管理系统中作者这个实体的属性应该有 (作者编号、作者姓名、*)。 (6)定义其他对象和规则 定义属性的数据型、长度、精度、非空、缺省值、约束规则等。定义触发器、存 储过程、视图、角色、同义词、序列
超级有影响力的Java面试题大全文档 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。 2.继承:  继承是一种联结的层次模型,并且允许和鼓励的重用,它提供了一种明确表述共性的方法。对象的一个新可以从现有的中派生,这个过程称为继承。新继承了原始的特性,新称为原始的派生(子),而原始称为新的基(父)。派生可以从它的基那里继承方法和实例变量,并且可以修改或增加新的方法使之更适合特殊的需要。 3.封装:  封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性:  多态性是指允许不同的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。 5、String是最基本的数据型吗?  基本数据型包括byte、int、char、long、float、double、boolean和short。  java.lang.String是final型的,因此不可以继承这个、不能修改这个。为了提高效率节省空间,我们应该用StringBuffer 6、int 和 Integer 有什么区别  Java 提供两种不同的型:引用型和原始型(或内置型)。Int是java的原始数据型,Integer是java为int提供的封装。Java为每个原始型提供了封装。 原始型 封装 boolean Boolean char Character byte Byte short Short int Integer long Long float Float double Double  引用型和原始型的行为完全不同,并且它们具有不同的语义。引用型和原始型具有不同的特征和用法,它们包括:大小和速度问题,这种型以哪种型的数据结构存储,当引用型和原始型用作某个的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始型实例变量的缺省值与它们的型有关。 7、StringStringBuffer的区别  JAVA平台提供了两个StringStringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String提供了数值不可改变的字符串。而这个StringBuffer提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用 StringBuffers来动态构造字符数据。 8、运行时异常与一般异常有何异同?  异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。 9、说出Servlet的生命周期,并说出Servlet和CGI的区别。  Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。 与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。 10、说出ArrayList,Vector, LinkedList的存储性能和特性  ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。 11、EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。 EJB包括Ses
JAVA相关基础知识 1、面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。 2.继承: 继承是一种联结的层次模型,并且允许和鼓励的重用,它提供了一种明确表述共性的方法。对象的一个新可以从现有的中派生,这个过程称为继承。新继承了原始的特性,新称为原始的派生(子),而原始称为新的基(父)。派生可以从它的基那里继承方法和实例变量,并且可以修改或增加新的方法使之更适合特殊的需要。 3.封装: 封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性: 多态性是指允许不同的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。 2、String是最基本的数据型吗? 基本数据型包括byte、int、char、long、float、double、boolean和short。 java.lang.String是final型的,因此不可以继承这个、不能修改这个。为了提高效率节省空间,我们应该用StringBuffer 3、int 和 Integer 有什么区别 Java 提供两种不同的型:引用型和原始型(或内置型)。Int是java的原始数据型,Integer是java为int提供的封装。Java为每个原始型提供了封装。 原始型封装 booleanBoolean charCharacter byteByte shortShort intInteger longLong floatFloat doubleDouble 引用型和原始型的行为完全不同,并且它们具有不同的语义。引用型和原始型具有不同的特征和用法,它们包括:大小和速度问题,这种型以哪种型的数据结构存储,当引用型和原始型用作某个的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始型实例变量的缺省值与它们的型有关。 4、StringStringBuffer的区别 JAVA平台提供了两个StringStringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String提供了数值不可改变的字符串。而这个StringBuffer提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。 5、运行时异常与一般异常有何异同? 异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。 6、说出Servlet的生命周期,并说出Servlet和CGI的区别。 Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。 与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。 7、说出ArrayList,Vector, LinkedList的存储性能和特性 ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。 8、EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。 EJB包括Session Bean、Entity Bean、Message Driven Bea
`XmlSerializer`是.NET中用于XML序列化和反序列化,但它无法直接序列化`Dictionary`字典对象。这是因为`Dictionary`在.NET中不是可序列化型。 `XmlSerializer`可以序列化和反序列化具有公共可读/可写属性的和结构,以及数组和集合型。但是,在序列化过程中,它无法处理键/值对的字典结构。 要序列化字典对象,你可以使用其他方法,例如将字典转换为可序列化型,或使用其他序列化库(如`DataContractSerializer`或`Json.NET`)。 如果你仍然希望使用`XmlSerializer`来序列化字典,你可以考虑创建一个序列化的封装来存储字典的键和值,并在需要时将其转换为字典。以下是一个示例代码: ```csharp using System; using System.Collections.Generic; using System.Xml.Serialization; public class SerializableDictionary<TKey, TValue> { [XmlArrayItem("Item")] public List<SerializableKeyValuePair<TKey, TValue>> Items { get; set; } public SerializableDictionary() { Items = new List<SerializableKeyValuePair<TKey, TValue>>(); } public SerializableDictionary(Dictionary<TKey, TValue> dictionary) { Items = new List<SerializableKeyValuePair<TKey, TValue>>(); foreach (var kvp in dictionary) { Items.Add(new SerializableKeyValuePair<TKey, TValue>(kvp.Key, kvp.Value)); } } public Dictionary<TKey, TValue> ToDictionary() { var dictionary = new Dictionary<TKey, TValue>(); foreach (var item in Items) { dictionary[item.Key] = item.Value; } return dictionary; } } public class SerializableKeyValuePair<TKey, TValue> { [XmlAttribute("Key")] public TKey Key { get; set; } [XmlAttribute("Value")] public TValue Value { get; set; } public SerializableKeyValuePair() { } public SerializableKeyValuePair(TKey key, TValue value) { Key = key; Value = value; } } public class Program { public static void Main() { // 创建一个字典 Dictionary<string, int> dictionary = new Dictionary<string, int>(); dictionary.Add("Apple", 1); dictionary.Add("Banana", 2); dictionary.Add("Orange", 3); // 将字典转换为可序列化型 var serializableDictionary = new SerializableDictionary<string, int>(dictionary); // 创建XmlSerializer对象并序列化字典 XmlSerializer serializer = new XmlSerializer(typeof(SerializableDictionary<string, int>)); using (var writer = new System.IO.StringWriter()) { serializer.Serialize(writer, serializableDictionary); string xml = writer.ToString(); Console.WriteLine(xml); } } } ``` 上述代码中,我们创建了一个`SerializableDictionary`,它包含一个`Items`属性,用于存储字典的键值对。然后,我们将字典转换为`SerializableDictionary`对象,并使用`XmlSerializer`将其序列化XML字符串。 希望这个示例可以帮助到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值