XML序列化数据对象(三)

来源:互联网 发布:指纹考勤机软件 编辑:程序博客网 时间:2024/05/16 05:30

XML序列化数据对象(三) --- 实现


一. 实现界面


1.1 大致界面



图1


1.2 类类型



图2


1.3 变量输入



图3


二. 使用步骤


2.1 添加一些类



图4


2.2 添加一些变量



图5


2.3 可以保存类型和变量为xml文件


添加了类型和变量后这些数据可以保存为xml文件(例如aa.xml), 也可以重新加载这个XML文件方便以后修改使用.

假设CTest类的结构变化了那么序列化/反序列化的代码也就需要改变了你可以重新加载aa.xmlCTest的结构修改然后再次生成序列化/反序列化代码即可.

aa.xml文件:

<structure_def><class name = "CTest"><include file = "a" sys = "0"></include><include file = "b" sys = "1"></include></class><basetype name = "int"></basetype><basetype name = "double"></basetype><basetype name = "long"></basetype><stltype name = "std::vector" typenamecount = "1"></stltype><stltemplate beptr = "0" beptr1 = "0" name = "IntVector" type = "std::vector" typename1 = "int"></stltemplate><ClassObject><m_nA class = "int"></m_nA><m_dB class = "double"></m_dB><m_intVector class = "IntVector"></m_intVector></ClassObject></structure_def>


2.4 生成序列化/反序列化的代码

#pragma once// 这里include你自己的头文件// 序列化class CHYSerialization{public:CHYSerialization();~CHYSerialization();bool SerializationOpen(const std::string& strFileName);bool SerializationClose();// 基本类型的序列化bool SerializationClassType_int(CHYMLItem* pCHYMLItemParent, const std::string& strObjectName, const int& nValue);bool SerializationClassType_long(CHYMLItem* pCHYMLItemParent, const std::string& strObjectName, const long& lValue);bool SerializationClassType_double(CHYMLItem* pCHYMLItemParent, const std::string& strObjectName, const double& dValue);bool SerializationClassType_float(CHYMLItem* pCHYMLItemParent, const std::string& strObjectName, const float& fValue);bool SerializationClassType_char(CHYMLItem* pCHYMLItemParent, const std::string& strObjectName, const char& chValue);bool SerializationClassType_string(CHYMLItem* pCHYMLItemParent, const std::string& strObjectName, const std::string& strValue);// 用户定义的类/结构体等类型的序列化bool SerializationClassType_CTest(CHYMLItem* pCHYMLItemParent, const std::string& strObjectName, const CTest& refValue);bool SerializationClassType_IntVector(CHYMLItem* pCHYMLItemParent, const std::string& strObjectName, const IntVector& refValue);// 变量的序列化函数bool SerializationObject_m_nA(const int& refValue);bool SerializationObject_m_dB(const double& refValue);bool SerializationObject_m_intVector(const IntVector& refValue);private:CHYML m_hyML;// 你使用的XML解析库相关变量CHYMLParser m_hyMLParser;CHYMLItem* m_pCHYMLItemParent;std::string m_strFileName;};// 反序列化class CHYReSerialization...// Cpp文件代码很长...


以上这些代码都是自动生成的, 随类型结构的变化而变化.

以后要序列化某类型的变量可以简单的生成这些代码即可.

h文件和cpp文件加入到你的工程即可.


2.5 序列化/反序列化的代码的使用


变量m_nA, m_dB, m_intVector本身就是你的工程里面需要才添加到代码生成器的.

序列化:

// 你工程里的变量是这样的int m_nA = 5;double m_dB = 5.9;IntVector m_intVector;m_intVector.push_back(1);m_intVector.push_back(3);m_intVector.push_back(4);m_intVector.push_back(7);....// 序列化CHYSerialization hySerialization;hySerialization.SerializationOpen("C:\ss.xml"); // 变量的序列化信息保存在ss.xml文件中// 序列化这3个变量hySerialization.SerializationObject_m_nA(m_nA);hySerialization.SerializationObject_m_dB(m_dB);hySerialization.SerializationObject_m_intVector(m_intVector);hySerialization.SerializationClose();

生成的变量的序列化信息ss.xml文件是

<ObjectSerialization><m_nA class = "int">5</m_nA><m_dB class = "double">5.900000</m_dB><m_intVector class = "IntVector"><vectorItem0 class = "int">1</vectorItem0><vectorItem1 class = "int">3</vectorItem1><vectorItem2 class = "int">4</vectorItem2><vectorItem3 class = "int">7</vectorItem3></m_intVector></ObjectSerialization>

反序列化:

CHYReSerialization hyReSerialization;hyReSerialization.ReSerializationOpen("C:\ss.xml");hyReSerialization.ReSerializationObject_m_nA(m_nA);hyReSerialization.ReSerializationObject_m_dB(m_dB);hyReSerialization.ReSerializationObject_m_intVector(m_intVector);hyReSerialization.ReSerializationClose();


初步使用了一下效果还可以.


三. 总结


3.1 这样自动生成序列化/反序列化的代码使用起来的确比较方便但是也有繁琐的地方例如生成代码后还要把h文件和cpp文件拷贝到自己的工程还要在h文件中添加相关的头文件(你的类头文件). 对比boost只需要些相关的模板代码代码就可以了.反正就是没有boost库方便.


3.2 添加类类型的处理非常非常的繁琐和乱因为类型很多(basetype, stltype, struct, class, stltemplate, typedef), 还有很多判断条件这些判断我是通过界面交互来处理的可能还有很多没有考虑到的地方可惜自己不懂C++的语法分析通过语法分析就很容易分析出这些类型而且更强大.


3.3 设计成类似boost库那样序列化的操作方式是不是更好?


3.4 用代码写代码需要在更高一层上想问题平时写代码你直接把代码写入对应的cpp/h文件然后编译看是否有语法错误编译通过了就运行看有没有运行上/逻辑上的错误;用代码写代码还要加多一层就是你先确保生成代码的程序(代码生成器)编译运行没错然后编译生成器生成的代码假设这代码有语法错误你需要返回到生成器工程对应的字符地方修改这些字符如果生成的代码语法没有但运行有错那还要分析你所设计的生成代码是否有问题这种过程是不断的在生成器代码和被生成代码之间切换编译生成拷贝编译..... (有时候会很乱!)


3.5 通过序列化/反序列化代码生成器体会到用代码写代码跟C++的模板编程(泛化编程)有与曲同工之妙必须在更高一层处想问题.当然泛化编程更规范更标准. (看这文章).


3.6 C++代码生成器生成代码生成的代码要编译后才能用这是因为C++的语言特性决定的假设我有一个代码生成器生成的代码不需要编译能直接使用那多好啊脚本语言可以(看这文章).