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

  最近自己无聊也用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>

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

 posted on 2011-05-18 00:06  john chen  阅读(1606)  评论(2编辑  收藏  举报