本次试验主要认识C#中操作Xml的两种方法:XDocument 和XmlDocument(还有第三种XmlReader,不喜欢这种,就不先去研究了)。再者在初窥序列化和反射。
0. 准备Xml文件
xml:
<?xml version="1.0" encoding="utf-8"?>
<Bookstore>
<!--记录书本的信息-->
<Book Type="必修课" ISBN="7-111-19149-2">
<Title>数据结构</Title>
<Author>严蔚敏</Author>
<Price>30.00</Price>
</Book>
<Book Type="必修课" ISBN="7-111-19149-3">
<Title>路由型与交换型互联网基础</Title>
<Author>程庆梅</Author>
<Price>27.00</Price>
</Book>
</Bookstore>
该方法支持LINQ。
private static void UseXDocument(string xmlpath)
{
XDocument xdoc = XDocument.Load(xmlpath);
<span style="white-space:pre"> </span> // Just declare, do not do query
var query = from e in xdoc.Descendants("Book")
select new Book()
{
Type = e.Attribute("Type").Value,
ISBN = e.Attribute("ISBN").Value,
Title = e.Element("Title").Value,
Author = e.Element("Author").Value,
Price = e.Element("Price").Value.ParseToDouble(),
};
PrintBook(query);<span style="white-space:pre"> </span>// Do the query here
Serializer.Serialize(query.First(), binpath);
}
最后一句序列化对象存储为bin文件,见本文附录A。
<span style="white-space:pre"> </span>private static void UseXmlDocument(string xmlpath)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlpath);
foreach (XmlNode node in doc.SelectNodes("Bookstore//Book"))
{
Book book = new Book();
// Set Field With Reflection
foreach (XmlAttribute attr in node.Attributes)
{
Reflector.SetField(book, attr.LocalName, attr.Value);
}
foreach (XmlNode child in node.ChildNodes)
{
Reflector.SetField(book, child.Name, child.InnerText);
}
PrintBook(book);
}
}
在设置对象字段时,应用了反射,见附录B
附录 A 序列化和反序列化
public static class Serializer
{
public static void Serialize(object obj, string binpath)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(binpath, FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();
}
public static T Deserialize<T>(string binpath) where T : class
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(binpath, FileMode.Open,
FileAccess.Read, FileShare.Read);
T target = formatter.Deserialize(stream) as T;
stream.Close();
return target;
}
}
附录 B 反射
public static class Reflector
{
public static void SetField(object obj, string field, string value)
{
try
{
FieldInfo fi = obj.GetType().GetField(field);
var fieldTypeName = fi.FieldType.Name;
// Parser Method Format: ParseTo + typename
// e.g.: ParseToUint32
MethodInfo mi = typeof(StringParser).GetMethod("ParseTo" + fieldTypeName);
var v = mi.Invoke(null, new object[] { value });
fi.SetValue(obj, v);
}
catch
{ }
}
}
附录 C String解析
public static class StringParser
{
public static string ParseToString(this string str)
{
return str;
}
public static int ParseToInt32(this string str)
{
try
{
return Convert.ToInt32(str);
}
catch
{
return default(int);
}
}
public static uint ParseToUInt32(this string str)
{
try
{
if (str.Contains("0x") || str.Contains("0X"))
{
return Convert.ToUInt32(str, 16);
}
return Convert.ToUInt32(str);
}
catch
{
return default(uint);
}
}
public static double ParseToDouble(this string str)
{
try
{
return Convert.ToDouble(str);
}
catch
{
return default(double);
}
}
public static bool ParseToBoolean(this string str)
{
try
{
if (str == "0")
{
return false;
}
if (str == "1")
{
return true;
}
return Convert.ToBoolean(str);
}
catch
{
return default(bool);
}
}
}