从二进制到xml,.NET框架为开发人员提供了很多序列化选项,甚至允许开发人员创建自己的序列化例程。在本文中,我将着重讨论xml的序列化,并告诉你如何利用这一内置的功能。
.NET框架提供的一种形式的序列化是xml序列化。在这种类型的序列化里,对象状态被以xml格式保存。这使得被序列化的对象能够被不同的系统取得并修改,甚至是那些不是用.NET编写的系统。另外一个优势是被序列化的对象对于人来说是可读和可写的——因此更新对象的方式莫过于打开写字板更改其值。
xml序列化常常被来远程控制项目和Web服务项目里,虽然你可能会在别的地方发现它,比如DataSet封送。在与Xpath查询和Predicate方法一起使用的时候,xml序列化能够被用来实现面向对象的数据库——我会在今后的文章里谈这方面的内容。
在.NET框架里利用内置的xml序列化方法相对较为容易。你只需要熟悉一些类和属性就可以开始使用简单的xml序列化了:
System.xml.Serialization命名空间:含有使用xml序列化所需要的类和功能。这个命名空间应该被放在使用xml序列化的类的顶部的一个“using”命令里。
xmlSerializer类:提供将对象序列化和反序列化的功能。
xmlIgnore属性:告诉xmlSerializer类跳过你不希望序列化的成员。
这个列表只不过让你对序列化有一个初步的了解。还有更多的对象可以供你在使用xml序列化的时候使用。
列表A是将Customer对象序列化的一个简单例子。这个Customer对象在下载文件的示例应用程序里被定义。
列表A
Customer customer = newCustomer();
customer.FirstName = "Zach";
customer.LastName = "Smith";
xmlSerializer serializer = newxmlSerializer(typeof(Customer));
StringWriter writer = newStringWriter();
serializer.Serialize(writer, customer);
Console.WriteLine(writer.ToString());
正如你看到的,xml序列化是一个很简单的过程。我们只需要创建一个需要被序列化的对象,创建用于这种类型对象的xmlSerializer,并调用xmlSerializer.Serialize。被序列化的对象然后被写到提供的Stream里——在本文中是一个叫做“writer”的StringWriter。
如果你看看被序列化的对象,你会注意到它很容易读懂。下面就是被序列化的Customer对象的内容:
<?xml version="1.0" encoding="utf-16"?>
<Customer xmlns:xsi=http://www.w3.org/2001/xmlSchema-instance xmlns:xsd="ttp://www.w3.org/2001/xmlSchema">
<Orders />
<LastName>Smith</LastName>
<FirstName>Zach</FirstName>
</Customer>
在这里,你会看到Customer对象的属性被序列化,也就是Order对象的列表。如果你将这个输出与Customer类的定义比较一下,你会注意到“Income”属性没有被列出来。这是因为Income属性本身还带有一个xmlIgnore属性,它会让xml序列化库在序列化的时候跳过Income属性。在序列化过程中跳过属性的一个副作用是这个属性不会被反序列化,所以会在反序列化的时候总是带有默认的值。
Orders节点是空的,因为这个客户没有下订单。但是如果我们将含有订单的Customer对象序列化,那么我们就会得到类似下面的输出:
<?xml version="1.0" encoding="utf-16"?>
<Customer xmlns:xsi="ttp://www.w3.org/2001/xmlSchema-instance" xmlns:xsd="ttp://www.w3.org/2001/xmlSchema">
<Orders>
<Order>
<Total>34.56</Total>
</Order>
<Order>
<Total>156.56</Total>
</Order>
</Orders>
<LastName>Smith</LastName>
<FirstName>Zach</FirstName>
</Customer>
要注意每个订单对象都被单独序列化并放在被序列化的Customer对象的Orders节点里。如果你想要反序列化这个Customer对象,那么相关联的Order对象也会被反序列化。
注:要被序列化或者反序列化的每个对象都必须有一个空的默认构造函数。如果对象不实现一个空的构造函数,那么就会引发异常。
反序列化对象
将对象反序列化就和将它们序列化一样简单。下面的代码(列表B)显示了如何将反序列化保存在文件里的对象:
列表B
xmlSerializer serializer = new xmlSerializer(typeof(Customer));
FileStream file = File.OpenRead(fileToWrite);
Customer customer = (Customer)serializer.Deserialize(file);
file.Close();
上面这段代码与前面的序列化代码的唯一不同之处在于我们在这里调用了xmlSerializer.Deserialize。这个方法会返回一个对象,我们然后就必须转到将要使用的对象类型上。
其他用法
在某些情况下,通过实现xml序列化来保存和检索设置文件是很有用的。例如,你可以只用创建一个含有所需属性的类并将它序列化到磁盘上,而不需要编写一个自定义的xml分析例程来寻找和分析设置文件。这还允许你在需要的时候对文件进行手动编辑,让你不需要自己编写任何xml分析代码。这种方式可以用于任何类型的信息,应用程序可能需要保存从一个执行到另一个执行的这种类型的信息。
正如我先前所说的,将xml序列化与Predicate方法(被编译的搜索)、Xpath(特别搜索),以及xmlDocument(提供器)对象一起使用,你可以创建一个面向对象的数据库,这是完全可行的。我已经在进行这样一个项目,所以我会在以后的文章里探讨它背后所隐藏的实现和思想。其目标是利用不超过200行的C#代码就创建完全可实现的面向对象的数据库。
既然你已经熟悉xml序列化了,那么我希望你能够在自己的项目里找到它的用武之地。从我个人来讲,我通过对复杂的应用程序设置使用xml序列化节省了大量的时间,这还不算上我应用程序的其他一些模块。所以我希望本文能够不让你犯我曾经犯过的错误!