zoukankan      html  css  js  c++  java
  • Xml系列化初体验

      很多时候做项目的时候都会需要数据测试,比如做分页时要进行分页测试就必须要有数据用来测试,而数据来源?数据库无疑是一个很好的选择,但这时要创建一个数据库再创建测试用的表,此时你是否会感觉麻烦了点?个人认为是有点麻烦。。。

      最近自己无聊也用jQuery做了个分页的控件,测试时就遇到了这个问题:数据来源的问题。本想就用数据库来测试的,但因为怕麻烦就想能不能有其他的比较好的方式来实现,因为类似需要一些数据测试的问题以后仍会遇到,就想着现在找一个好的方法来解决它。就有了编写个符合自己需求的xml系列化的方法。

      系列化xml,一开始想到的是.Net Framework里的XmlSerializer,代码如下:

    /// <summary>
    /// 序列化
    /// </summary>
    /// <param name="obj">对象</param>
    /// <param name="filepath">文件路径</param>
    public static bool Save(object obj, string filepath)
    {
    bool success = false;
    FileStream fs
    = null;
    try
    {
    fs
    = new FileStream(filepath, FileMode.Create, FileAccess.ReadWrite);
    XmlSerializer serializer
    = new XmlSerializer(obj.GetType());
    serializer.Serialize(fs, obj);
    success
    = true;
    }
    catch (Exception ex)
    {

    throw ex;
    }
    finally
    {
    if (fs != null)
    {
    fs.Close();
    fs.Dispose();
    }
    }
    return success;
    }

    /// <summary>
    /// 反系列化
    /// </summary>
    /// <param name="type">对象类型</param>
    /// <param name="filepath">文件路径</param>
    /// <returns></returns>
    public static object Load(Type type, string filepath)
    {
    FileStream fs
    = null;
    try
    {
    fs
    = new FileStream(filepath, FileMode.Open, FileAccess.ReadWrite);
    XmlSerializer serializer
    = new XmlSerializer(type);
    return serializer.Deserialize(fs);
    }
    catch (Exception ex)
    {

    throw ex;
    }
    finally
    {
    if (fs != null)
    {
    fs.Close();
    fs.Dispose();
    }
    }
    }

      如上,其实挺简单的,可测试才发现这并不能实现自己想要的效果...

      所以没办法就自己写了一个简单的方法:

    /// <summary>
    /// 将object对象系列化成xml
    /// </summary>
    /// <param name="obj">可系列化的对象</param>
    /// <param name="filename">文件路径</param>
    public static XmlDocument XmlSerialize(string filename, object obj)
    {
    FileInfo fileInfo
    = new FileInfo(filename);
    if (!fileInfo.Exists) //不存在文件创建文件
    {
    CreateFile(filename);
    }
    XmlDocument xmlDoc
    = new XmlDocument();
    string name = obj.GetType().Name;
    xmlDoc.Load(filename);
    XmlNode node
    = xmlDoc.SelectSingleNode("Entity");
    CreateSubElement(
    ref xmlDoc, node, obj, name);
    xmlDoc.Save(filename);
    return xmlDoc;
    }

    /// <summary>
    /// 创建子元素
    /// </summary>
    /// <param name="xmlDoc">需要创建子元素的xml文档</param>
    /// <param name="obj">要系列化的对象</param>
    public static void CreateSubElement(ref XmlDocument xmlDoc, XmlNode node, object obj, string name)
    {
    XmlElement root
    = xmlDoc.CreateElement(name); //子元素根
    node.AppendChild(root);
    foreach (var item in obj.GetType().GetProperties())
    {
    string value = "Null";
    var objValue
    = item.GetValue(obj, null);
    var proName
    = item.Name;
    Type type
    = item.PropertyType;
    bool isClass = IsClass(type); //判断属性类型是否为类
    if (isClass)
    {
    object o = CreateExample(type);
    string filename = XmlHelper.GetFileName(type.Name);
    FileInfo fileInfo
    = new FileInfo(filename);
    if (!fileInfo.Exists) //不存在引用对象文件,则创建引用对象文件
    {
    CreateFile(filename);
    }
    CreateSubElement(
    ref xmlDoc, root, o, type.Name);
    continue;
    }
    if (objValue != null)
    {
    value
    = objValue.ToString();
    }
    XmlElement element
    = xmlDoc.CreateElement(proName);
    element.SetAttribute(
    "DataType", item.PropertyType.Name); //添加属性类型名称
    element.InnerText = value;
    root.AppendChild(element);
    }
    }

    /// <summary>
    /// 根据TypeCode枚举判读是否为引用对象
    /// </summary>
    /// <param name="type">判断类型</param>
    /// <returns></returns>
    public static bool IsClass(Type type)
    {
    string[] typeCodeNameArray = Enum.GetNames(typeof(TypeCode));
    foreach (string item in typeCodeNameArray)
    {
    if (type.Name == item)
    {
    return false;
    }
    }
    return true;
    }
    /// <summary>
    /// 创建Xml文件
    /// </summary>
    /// <param name="filename">文件路径</param>
    public static void CreateFile(string filename)
    {
    FileStream stream
    = null;
    XmlWriter xmlWriter
    = null;
    try
    {
    stream
    = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite);
    XmlDocument xmlDoc
    = new XmlDocument();
    XmlDeclaration declaration
    = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
    XmlNode rootNode
    = xmlDoc.CreateNode(XmlNodeType.Element, null, "Entity", null);
    rootNode.InnerText
    = "";
    xmlDoc.AppendChild(declaration);
    xmlDoc.InsertAfter(rootNode, declaration);
    xmlWriter
    = XmlWriter.Create(stream);
    xmlDoc.WriteTo(xmlWriter);
    }
    catch (Exception ex)
    {
    throw ex;
    }
    finally
    {
    if (xmlWriter != null) xmlWriter.Close();
    if (stream != null) stream.Close();
    }
    }

       以下是创建对象实例方法:

    /// <summary>
    /// 创建对象实例
    /// </summary>
    /// <param name="type">对象类型</param>
    /// <returns></returns>
    public static object CreateExample(Type type)
    {
    object obj = Activator.CreateInstance(type);
    return obj;
    }

       因为要保存N条数据,所以自己定制了一个Xml文件的格式,如下:

    <?xml version="1.0" encoding="utf-8"?>
    <Entity>
    </Entity>
    Entity为xml的根节点。

      其实思路挺简单的,将要系列化的对象和文件路径传入,判断项目中是否存在以该xml文件,如果不存在则创建,先前说过xml文件格式有个限制(其格式如上),然后根据对象属性名称/值,创建xml元素,相应的判断属性是否为引用对象如果是创建相应的引用对象。

      呵呵、这表述能力实在无法恭维。哎。。。至于反系列化就不多说了,直接给代码:

    /// <summary>
    /// 反系列化xml
    /// </summary>
    /// <param name="type">可系列化的对象类型</param>
    /// <param name="xmlNode">xml中对象对应的节点</param>
    /// <returns></returns>
    public static object XmlDeserialize(Type type,XmlNode xmlNode)
    {
    XmlElement xe
    = (XmlElement)xmlNode;
    object parentObj = CreateExample(type);
    foreach (var parentItem in parentObj.GetType().GetProperties())
    {
    var parentSetobj
    = parentObj.GetType().GetProperty(parentItem.Name);
    XmlElement xmlElement
    = (XmlElement)xe.SelectSingleNode(parentItem.Name);
    Type parentType
    = parentItem.PropertyType;
    bool isClass = IsClass(parentType);
    if (isClass)
    {
    object subObj = CreateExample(parentType);
    string subName = subObj.GetType().Name;
    XmlNode subNode
    = xe.SelectSingleNode(subName);
    foreach (var subItem in subObj.GetType().GetProperties())
    {
    XmlElement subxl
    = (XmlElement)subNode;
    var subSetobj
    = subObj.GetType().GetProperty(subItem.Name);
    Type proType
    = subItem.PropertyType;
    if (IsClass(proType))
    {
    subObj
    = XmlDeserialize(subObj.GetType(), subNode);
    continue;
    }
    object value = Convert.ChangeType(subxl.SelectSingleNode(subItem.Name).InnerText, proType);
    subSetobj.SetValue(subObj, value,
    null);
    }
    parentSetobj.SetValue(parentObj, subObj,
    null);
    continue;
    }
    object parentValue = Convert.ChangeType(xmlElement.InnerText, parentType);
    parentSetobj.SetValue(parentObj, parentValue,
    null);
    }
    return parentObj;
    }

      系列化和反系列化实现以后,相应的就是对系列化后的文件进行增、删、改、查操作了,这些在整理,以后再上源码。

      以下是系列化后文件:

    <?xml version="1.0" encoding="utf-8"?>
    <Entity>
    <Student>
    <StudentNo DataType="String">001</StudentNo>
    <Name DataType="String">MrChen</Name>
    <Sex DataType="String"></Sex>
    <BirthDay DataType="DateTime">1989-5-14 22:05:01</BirthDay>
    <Course>
    <CourseNo DataType="String">Null</CourseNo>
    <CourseName DataType="String">Null</CourseName>
    <Id DataType="String">ab0a7aa2-4295-4fe6-910c-1e61c47a942c</Id>
    <CreateTime DataType="DateTime">2011-5-14 22:05:01</CreateTime>
    <IsDelete DataType="Boolean">False</IsDelete>
    <Version DataType="DateTime">2011-5-14 22:05:01</Version>
    </Course>
    <Id DataType="String">295afde9-b5ce-465c-b267-ae948cce3ec7</Id>
    <CreateTime DataType="DateTime">2011-5-14 22:05:01</CreateTime>
    <IsDelete DataType="Boolean">False</IsDelete>
    <Version DataType="DateTime">2011-5-14 22:05:01</Version>
    </Student>
    <Student>
    <StudentNo DataType="String">002</StudentNo>
    <Name DataType="String">MrChen</Name>
    <Sex DataType="String"></Sex>
    <BirthDay DataType="DateTime">1989-5-14 22:05:43</BirthDay>
    <Course>
    <CourseNo DataType="String">Null</CourseNo>
    <CourseName DataType="String">Null</CourseName>
    <Id DataType="String">fb674255-0af9-4863-b2dc-b29b112b4ad5</Id>
    <CreateTime DataType="DateTime">2011-5-14 22:05:43</CreateTime>
    <IsDelete DataType="Boolean">False</IsDelete>
    <Version DataType="DateTime">2011-5-14 22:05:43</Version>
    </Course>
    <Id DataType="String">8ccafe8c-5d7b-4e1d-9721-c8393e392929</Id>
    <CreateTime DataType="DateTime">2011-5-14 22:05:43</CreateTime>
    <IsDelete DataType="Boolean">False</IsDelete>
    <Version DataType="DateTime">2011-5-14 22:05:43</Version>
    </Student>
    </Entity>

    而反系列化后就是一个对象了。

  • 相关阅读:
    html5 返回当前地理位置的坐标点(经纬度)
    C#趣味程序---百鸡百钱
    Android开发:怎样隐藏自己的app应用
    Android Studio一些简单设置
    集群通信组件tribes之集群的消息接收通道
    Java基础实例
    如何用webbrowser获取ajax动态生成的网页的源码?
    phantomjs 下拉滚动条获取网页的全部源码
    Nodejs+定时截图+发送邮件
    关注网页的更新状况,了解最新的handsup 消息.
  • 原文地址:https://www.cnblogs.com/chenyt/p/2046850.html
Copyright © 2011-2022 走看看