xml 之 十二 串行化
        xml 是设计用于在各种不同的系统之间进行数据交换的技术。您可以轻松地在分布式组件之间传送xml,这归功于他的平台独立性、简介、基于文本、自描述格式,然而这些却很难构成可靠编程平台的基础。基于文本的数据没有强类型安全规则。程序员往往易受面向对象模式的诱惑,因为每个对象都属于某一类型,因为编译器可警惕潜在的类型问题,对象中封装的数据可以轻松的访问到。理想的编程环境是用面向对象的模型构建软件,但是充分利用xml在分布式组件(如在Internet 或 Messae Queue 中)之间优势。这就是xml串行化之所以重要的原因:它提供了一座桥梁,使您能够不露痕迹地将对象转换为xml,反之亦然。
        xml串行化是将数据的集合转换为信息流的过程。反串行化则是相反的过程:将信息流转换回原先生成该信息流的数据。有时将这两个相逆的过程称为脱水(dehydration)和水合(rehydration)。
下面将详细介绍以下内容:
1.xml串行化
2.如何将对象串行化为xml格式
3.用XmlSerializer类串行化对象图
4.用设计时间属性自定义串行化输出
5.在xml串行化期间处理命名空间
6.如何将xml表示反串行化为对象
7.用XmlSerializer类串行化和反串行化通用类型
8.通过使用新增的xml Serializer Gdnerator 工具改进串行化性能
串行化入门
串行化是运行时进程,将对象或对象的图转换为线性序列字节,然后可以将合成的内存块用于存储或通过特定协议在网络间传输。在.net framework 中,对象串行化可以有3种不同的输出格式:
Binary (二进制) -------- 将对象格式化为二进制
Simple Object Access Protocol (SOAP)  ---------- 将对象格式化为SOAP格式
XML  ------------ 将对象格式化为XML格式,从而可以传输到另一种应用程序中
运行时对象串行化(二进制和SOAP) 和 XML格式是非常不同的两种技术,不仅实现方式不同,更重要的目标不同。尽管如此,这两种形式都完成同一关键的事情:保存内容、内存外的活动对象,并从内存转移到其他任何存储介质。
注意:
System.Runtime.Serialization 命名空间中包含的格式化程序命名空间和类支持二进制和SOAP串行化。XML串行化主要由Sytem.Xml.Serialization命名空间中的XmlSerializer类支持。
串行化对于用简单的格式传输或存储复杂的数据很有用,例如,应用程序可以构建包含几十个对象的复杂数据结构,并将它串行化为文本字符串。然后可以通过网络将字符串传送到另一个程序。接受程序将反串行化文本,从而构建一个原始数据结构的副本。串行化不必将对象转换为文本。它可以将对象表示为二进制数据流。它也不必通过网络传送数据。串行化的这些用途有一个共同的特点:将可能非常复杂的数据通信转换为简单的串行表示,然后转换回来。
1.1 XmlSerializer 
XmlSerializer.Serialize()方法的第一个参数是重写的,因此可以将XML串行化为Stream, TextWriter, XmlWriter
XmlSerializer 类在Sytem.Xml.Serialization命名空间的详细信息自己查询msdn,在这里不介绍了。
1.串行化对象
首先是创建要通过XmlSerializer 类串行化的类
                                                                        程序清单12-1
 using System;
using System;
 [Serializable]
[Serializable] public class Category
public class Category {
{ public long CategoryID;
    public long CategoryID; public string CategoryName;
    public string CategoryName; public string Description;
    public string Description; }
}接下来就可以串行化该类并将其转换为xml格式。
程序清单12-2
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %>
 <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server"> void Page_Load(object sender, System.EventArgs e)
    void Page_Load(object sender, System.EventArgs e) {
    { string xmlFilePath = @"C:\Data\Category.xml";
        string xmlFilePath = @"C:\Data\Category.xml"; Category categoryObj = new Category();
        Category categoryObj = new Category(); categoryObj.CategoryID = 1;
        categoryObj.CategoryID = 1; categoryObj.CategoryName = "Beverages";
        categoryObj.CategoryName = "Beverages"; categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales";
        categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales"; XmlSerializer serializer = new XmlSerializer(typeof(Category));
        XmlSerializer serializer = new XmlSerializer(typeof(Category)); TextWriter writer = new StreamWriter(xmlFilePath);
        TextWriter writer = new StreamWriter(xmlFilePath); //Serialize the Category and close the TextWriter
        //Serialize the Category and close the TextWriter serializer.Serialize(writer, categoryObj);
        serializer.Serialize(writer, categoryObj); writer.Close();
        writer.Close(); Response.Write("File written successfully");
        Response.Write("File written successfully"); }
    } </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">
<head runat="server"> <title>Simple XML Serialization</title>
    <title>Simple XML Serialization</title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
        <div> </div>
        </div> </form>
    </form> </body>
</body> </html>
</html>打开Category.xml文件
 <?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?> <Category xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Category xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <CategoryID>1</CategoryID>
  <CategoryID>1</CategoryID> <CategoryName>Beverages</CategoryName>
  <CategoryName>Beverages</CategoryName> <Description>Soft drinks, coffees, teas, beers, and ales</Description>
  <Description>Soft drinks, coffees, teas, beers, and ales</Description> </Category>
</Category>Category类所有公有字段都串行化到xml元素中,其名称和类声明中的字段名相同。所有这些元素包含在根目录Category 元素中,该元素映射回类的名称。
2.处理对象图
同样的机制也可以用来串行化相关对象的整个图。例如Category类可以将所有产品(属于同样的类别)封装为一个嵌套元素。
 using System;
using System;
 public class Product
public class Product {
{ public long ProductID;
    public long ProductID; public string ProductName;
    public string ProductName;     public string QuantityPerUnit;
    public string QuantityPerUnit;     public string UnitPrice;
    public string UnitPrice;     public int UnitsInStock;
    public int UnitsInStock; }
}与Category类相似,product类也由一些公有属性组成。
把下面这行代码添加到Category类中。
public Product[] products;
 using System;
using System; [Serializable]
[Serializable] public class Category
public class Category {
{ public long CategoryID;
    public long CategoryID; public string CategoryName;
    public string CategoryName; public string Description;
    public string Description; public Product[] Products;
        public Product[] Products; }
}现在,您想串行化Category类,那么也会产生要串行化的Products数组。
程序清单12-5
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %>
 <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server"> void Page_Load(object sender, System.EventArgs e)
    void Page_Load(object sender, System.EventArgs e) {
    { string xmlFilePath = @"C:\Data\Category.xml";
        string xmlFilePath = @"C:\Data\Category.xml"; Category categoryObj = new Category();
        Category categoryObj = new Category(); categoryObj.CategoryID = 1;
        categoryObj.CategoryID = 1; categoryObj.CategoryName = "Beverages";
        categoryObj.CategoryName = "Beverages"; categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales";
        categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales"; //Populate the products array
        //Populate the products array Product prodObj = new Product();
        Product prodObj = new Product(); prodObj.ProductID = 1;
        prodObj.ProductID = 1; prodObj.ProductName = "Chai";
        prodObj.ProductName = "Chai"; prodObj.QuantityPerUnit = "10 boxes x 20 bags";
        prodObj.QuantityPerUnit = "10 boxes x 20 bags"; prodObj.UnitPrice = "18";
        prodObj.UnitPrice = "18"; prodObj.UnitsInStock = 39;
        prodObj.UnitsInStock = 39; //Insert the item into the array.
        //Insert the item into the array. Product[] products = { prodObj };
        Product[] products = { prodObj }; categoryObj.Products = products;
        categoryObj.Products = products; XmlSerializer serializer = new XmlSerializer(typeof(Category));
        XmlSerializer serializer = new XmlSerializer(typeof(Category)); TextWriter writer = new StreamWriter(xmlFilePath);
        TextWriter writer = new StreamWriter(xmlFilePath); // Serialize the Category and close the TextWriter
        // Serialize the Category and close the TextWriter serializer.Serialize(writer, categoryObj);
        serializer.Serialize(writer, categoryObj); writer.Close();
        writer.Close(); Response.Write("File written successfully");
        Response.Write("File written successfully"); }
    } </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">
<head runat="server"> <title>Nesting Objects during XML Serialization</title>
    <title>Nesting Objects during XML Serialization</title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
        <div> </div>
        </div> </form>
    </form> </body>
</body> </html>
</html>打开Category.xml文件
 <?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?> <Category xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Category xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <CategoryID>1</CategoryID>
  <CategoryID>1</CategoryID> <CategoryName>Beverages</CategoryName>
  <CategoryName>Beverages</CategoryName> <Description>Soft drinks, coffees, teas, beers, and ales</Description>
  <Description>Soft drinks, coffees, teas, beers, and ales</Description> <Products>
  <Products> <Product>
    <Product> <ProductID>1</ProductID>
      <ProductID>1</ProductID> <ProductName>Chai</ProductName>
      <ProductName>Chai</ProductName> <QuantityPerUnit>10 boxes x 20 bags</QuantityPerUnit>
      <QuantityPerUnit>10 boxes x 20 bags</QuantityPerUnit> <UnitPrice>18</UnitPrice>
      <UnitPrice>18</UnitPrice> <UnitsInStock>39</UnitsInStock>
      <UnitsInStock>39</UnitsInStock> </Product>
    </Product> </Products>
  </Products> </Category>
</Category>高级串行化
        在前面几个例子中,类的公有字段直接映射到输出xml文档的xml元素中。虽然这个一对一的映射方法对简单串行化场景有效,然而有时候却需要您自定义生成的输出。幸运的是,xml串行化使您可以自定义要创建的xml数据的最终的输出结果。
1.xml串行化属性(Attrbute)
XmlAttributes类表示.net framework 属性的集合,这个集合使您能够联系XmlSerializer类如何处理对象的完整控件
说明:
XmlAttributes类与SoapAttributes类相似,只有一点不同:XmlAttributes类的输出为xml格式,而SoapAttributes类返回带类型信息的SOAP编码消息。
XmlAttributes类的每个属性都对应于一个属性类。
 namespace System.Xml.Serialization
namespace System.Xml.Serialization {
{ // 摘要:
    // 摘要: //     表示一个属性对象的集合,这些对象控制 System.Xml.Serialization.XmlSerializer 如何序列化和反序列化对象。
    //     表示一个属性对象的集合,这些对象控制 System.Xml.Serialization.XmlSerializer 如何序列化和反序列化对象。 public class XmlAttributes
    public class XmlAttributes {
    { // 摘要:
        // 摘要: //     初始化 System.Xml.Serialization.XmlAttributes 类的新实例。
        //     初始化 System.Xml.Serialization.XmlAttributes 类的新实例。 public XmlAttributes();
        public XmlAttributes(); //
        // // 摘要:
        // 摘要: //     初始化 System.Xml.Serialization.XmlAttributes 类的新实例,并自定义 System.Xml.Serialization.XmlSerializer
        //     初始化 System.Xml.Serialization.XmlAttributes 类的新实例,并自定义 System.Xml.Serialization.XmlSerializer //     序列化和反序列化对象的方式。
        //     序列化和反序列化对象的方式。 //
        // // 参数:
        // 参数: //   provider:
        //   provider: //     能提供控制 XML 序列化的属性的其他实现的类。
        //     能提供控制 XML 序列化的属性的其他实现的类。 public XmlAttributes(ICustomAttributeProvider provider);
        public XmlAttributes(ICustomAttributeProvider provider);
 // 摘要:
        // 摘要: //     获取或设置要重写的 System.Xml.Serialization.XmlAnyAttributeAttribute。
        //     获取或设置要重写的 System.Xml.Serialization.XmlAnyAttributeAttribute。 //
        // // 返回结果:
        // 返回结果: //     要重写的 System.Xml.Serialization.XmlAnyAttributeAttribute。
        //     要重写的 System.Xml.Serialization.XmlAnyAttributeAttribute。 public XmlAnyAttributeAttribute XmlAnyAttribute { get; set; }
        public XmlAnyAttributeAttribute XmlAnyAttribute { get; set; } //
        // // 摘要:
        // 摘要: //     获取要重写的 System.Xml.Serialization.XmlAnyElementAttribute 对象集合。
        //     获取要重写的 System.Xml.Serialization.XmlAnyElementAttribute 对象集合。 //
        // // 返回结果:
        // 返回结果: //     表示 System.Xml.Serialization.XmlAnyElementAttribute 对象集合的 System.Xml.Serialization.XmlAnyElementAttributes
        //     表示 System.Xml.Serialization.XmlAnyElementAttribute 对象集合的 System.Xml.Serialization.XmlAnyElementAttributes //     对象。
        //     对象。 public XmlAnyElementAttributes XmlAnyElements { get; }
        public XmlAnyElementAttributes XmlAnyElements { get; } //
        // // 摘要:
        // 摘要: //     获取或设置一个对象,该对象指定 System.Xml.Serialization.XmlSerializer 如何序列化返回数组的公共字段或读/写属性。
        //     获取或设置一个对象,该对象指定 System.Xml.Serialization.XmlSerializer 如何序列化返回数组的公共字段或读/写属性。 //
        // // 返回结果:
        // 返回结果: //     System.Xml.Serialization.XmlArrayAttribute,指定 System.Xml.Serialization.XmlSerializer
        //     System.Xml.Serialization.XmlArrayAttribute,指定 System.Xml.Serialization.XmlSerializer //     序列化返回数组的公共字段或读/写属性的方式。
        //     序列化返回数组的公共字段或读/写属性的方式。 public XmlArrayAttribute XmlArray { get; set; }
        public XmlArrayAttribute XmlArray { get; set; } //
        // // 摘要:
        // 摘要: //     获取或设置一个对象集合,这些对象指定 System.Xml.Serialization.XmlSerializer 如何序列化插入数组(该数组由公共字段或读/写属性返回)的项。
        //     获取或设置一个对象集合,这些对象指定 System.Xml.Serialization.XmlSerializer 如何序列化插入数组(该数组由公共字段或读/写属性返回)的项。 //
        // // 返回结果:
        // 返回结果: //     System.Xml.Serialization.XmlArrayItemAttributes 对象,它包含 System.Xml.Serialization.XmlArrayItemAttribute
        //     System.Xml.Serialization.XmlArrayItemAttributes 对象,它包含 System.Xml.Serialization.XmlArrayItemAttribute //     对象的集合。
        //     对象的集合。 public XmlArrayItemAttributes XmlArrayItems { get; }
        public XmlArrayItemAttributes XmlArrayItems { get; } //
        // // 摘要:
        // 摘要: //     获取或设置一个对象,该对象指定 System.Xml.Serialization.XmlSerializer 如何将公共字段或公共读/写属性 (Property)
        //     获取或设置一个对象,该对象指定 System.Xml.Serialization.XmlSerializer 如何将公共字段或公共读/写属性 (Property) //     作为 XML 属性 (Attribute) 序列化。
        //     作为 XML 属性 (Attribute) 序列化。 //
        // // 返回结果:
        // 返回结果: //     控制将公共字段或读/写属性 (Property) 序列化为 XML 属性 (Attribute) 的 System.Xml.Serialization.XmlAttributeAttribute。
        //     控制将公共字段或读/写属性 (Property) 序列化为 XML 属性 (Attribute) 的 System.Xml.Serialization.XmlAttributeAttribute。 public XmlAttributeAttribute XmlAttribute { get; set; }
        public XmlAttributeAttribute XmlAttribute { get; set; } //
        // // 摘要:
        // 摘要: //     获取或设置一个对象,该对象允许区别一组选项。
        //     获取或设置一个对象,该对象允许区别一组选项。 //
        // // 返回结果:
        // 返回结果: //     可应用到某个类成员(被序列化为 xsi:choice 元素)的 System.Xml.Serialization.XmlChoiceIdentifierAttribute。
        //     可应用到某个类成员(被序列化为 xsi:choice 元素)的 System.Xml.Serialization.XmlChoiceIdentifierAttribute。 public XmlChoiceIdentifierAttribute XmlChoiceIdentifier { get; }
        public XmlChoiceIdentifierAttribute XmlChoiceIdentifier { get; } //
        // // 摘要:
        // 摘要: //     获取或设置 XML 元素或属性的默认值。
        //     获取或设置 XML 元素或属性的默认值。 //
        // // 返回结果:
        // 返回结果: //     表示 XML 元素或属性的默认值的 System.Object。
        //     表示 XML 元素或属性的默认值的 System.Object。 public object XmlDefaultValue { get; set; }
        public object XmlDefaultValue { get; set; } //
        // // 摘要:
        // 摘要: //     获取一个对象集合,这些对象指定 System.Xml.Serialization.XmlSerializer 将公共字段或读/写属性序列化为 XML
        //     获取一个对象集合,这些对象指定 System.Xml.Serialization.XmlSerializer 将公共字段或读/写属性序列化为 XML //     元素的方式。
        //     元素的方式。 //
        // // 返回结果:
        // 返回结果: //     包含一个 System.Xml.Serialization.XmlElementAttribute 对象集合的 System.Xml.Serialization.XmlElementAttributes。
        //     包含一个 System.Xml.Serialization.XmlElementAttribute 对象集合的 System.Xml.Serialization.XmlElementAttributes。 public XmlElementAttributes XmlElements { get; }
        public XmlElementAttributes XmlElements { get; } //
        // // 摘要:
        // 摘要: //     获取或设置一个对象,该对象指定 System.Xml.Serialization.XmlSerializer 如何序列化枚举成员。
        //     获取或设置一个对象,该对象指定 System.Xml.Serialization.XmlSerializer 如何序列化枚举成员。 //
        // // 返回结果:
        // 返回结果: //     指定 System.Xml.Serialization.XmlSerializer 如何序列化枚举成员的 System.Xml.Serialization.XmlEnumAttribute。
        //     指定 System.Xml.Serialization.XmlSerializer 如何序列化枚举成员的 System.Xml.Serialization.XmlEnumAttribute。 public XmlEnumAttribute XmlEnum { get; set; }
        public XmlEnumAttribute XmlEnum { get; set; } //
        // // 摘要:
        // 摘要: //     获取或设置一个值,该值指定 System.Xml.Serialization.XmlSerializer 是否序列化公共字段或公共读/写属性。
        //     获取或设置一个值,该值指定 System.Xml.Serialization.XmlSerializer 是否序列化公共字段或公共读/写属性。 //
        // // 返回结果:
        // 返回结果: //     如果 System.Xml.Serialization.XmlSerializer 不应序列化字段或属性,则为 true;否则为 false。
        //     如果 System.Xml.Serialization.XmlSerializer 不应序列化字段或属性,则为 true;否则为 false。 public bool XmlIgnore { get; set; }
        public bool XmlIgnore { get; set; } //
        // // 摘要:
        // 摘要: //     获取或设置一个值,该值指定当重写包含返回 System.Xml.Serialization.XmlSerializerNamespaces 对象的成员的对象时,是否保留所有的命名空间声明。
        //     获取或设置一个值,该值指定当重写包含返回 System.Xml.Serialization.XmlSerializerNamespaces 对象的成员的对象时,是否保留所有的命名空间声明。 //
        // // 返回结果:
        // 返回结果: //     如果应保留命名空间声明,则为 true;否则为 false。
        //     如果应保留命名空间声明,则为 true;否则为 false。 public bool Xmlns { get; set; }
        public bool Xmlns { get; set; } //
        // // 摘要:
        // 摘要: //     获取或设置一个对象,该对象指定 System.Xml.Serialization.XmlSerializer 如何将类作为 XML 根元素序列化。
        //     获取或设置一个对象,该对象指定 System.Xml.Serialization.XmlSerializer 如何将类作为 XML 根元素序列化。 //
        // // 返回结果:
        // 返回结果: //     重写作为 XML 根元素属性化的类的 System.Xml.Serialization.XmlRootAttribute。
        //     重写作为 XML 根元素属性化的类的 System.Xml.Serialization.XmlRootAttribute。 public XmlRootAttribute XmlRoot { get; set; }
        public XmlRootAttribute XmlRoot { get; set; } //
        // // 摘要:
        // 摘要: //     获取或设置一个对象,该对象指示 System.Xml.Serialization.XmlSerializer 将公共字段或公共读/写属性作为 XML
        //     获取或设置一个对象,该对象指示 System.Xml.Serialization.XmlSerializer 将公共字段或公共读/写属性作为 XML //     文本序列化。
        //     文本序列化。 //
        // // 返回结果:
        // 返回结果: //     重写公共属性或字段的默认序列化的 System.Xml.Serialization.XmlTextAttribute。
        //     重写公共属性或字段的默认序列化的 System.Xml.Serialization.XmlTextAttribute。 public XmlTextAttribute XmlText { get; set; }
        public XmlTextAttribute XmlText { get; set; } //
        // // 摘要:
        // 摘要: //     获取或设置一个对象,该对象指定 System.Xml.Serialization.XmlSerializer 如何序列化一个已对其应用 System.Xml.Serialization.XmlTypeAttribute
        //     获取或设置一个对象,该对象指定 System.Xml.Serialization.XmlSerializer 如何序列化一个已对其应用 System.Xml.Serialization.XmlTypeAttribute //     的类。
        //     的类。 //
        // // 返回结果:
        // 返回结果: //     重写应用于类声明的 System.Xml.Serialization.XmlTypeAttribute 的 System.Xml.Serialization.XmlTypeAttribute。
        //     重写应用于类声明的 System.Xml.Serialization.XmlTypeAttribute 的 System.Xml.Serialization.XmlTypeAttribute。 public XmlTypeAttribute XmlType { get; set; }
        public XmlTypeAttribute XmlType { get; set; } }
    } }
}
 xml串行化的一个好处是,它使您能够控制要生成的xml文档的结构。您可以将特殊属性(上表)应用到这个类的成员来完成该功能。下面显示了带xml串行化属性的Category类。
 using System;
using System; using System.Xml;
using System.Xml; using System.Xml.Serialization;
using System.Xml.Serialization;
 [XmlRoot("CategoryRoot", Namespace = "http://www.wrox.com", IsNullable = false)]
[XmlRoot("CategoryRoot", Namespace = "http://www.wrox.com", IsNullable = false)] public class Category
public class Category {
{ [XmlAttribute("ID")]
    [XmlAttribute("ID")] public long CategoryID;
    public long CategoryID; [XmlAttribute("Name")]
    [XmlAttribute("Name")] public string CategoryName;
    public string CategoryName; [XmlElementAttribute(IsNullable = false)]
    [XmlElementAttribute(IsNullable = false)] public string Description;
    public string Description; }
}对Category类做了这些修改后,如果您从浏览器请求程序清单12-2中所示的aspx页时,打开生成的Category.xml应看到下面代码:
 <?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?> <CategoryRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
<CategoryRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"  ID="1" Name="Beverages" xmlns="http://www.wrox.com">
              ID="1" Name="Beverages" xmlns="http://www.wrox.com"> <Description>Soft drinks, coffees, teas, beers, and ales</Description>
  <Description>Soft drinks, coffees, teas, beers, and ales</Description> </CategoryRoot>
</CategoryRoot>正如您所看到的,已经用XmlRoot属性类将根元素重命名为CategoryRoot。作为XmlRoot属性的一部分,您也可以为Namespace 和 IsNullable 属性指定值。然后,CategoryID、CategoryName 元素将被分别重命名为ID、Name,这两者也将作为属性创建。
2.用XmlAttributeOverride控制输出
前面介绍了如何用硬编码的xml串行化属性的方式来重写xml元素。
说明:
在运行时重写xml元素的功能是非常有用的,可以是很多场景有用。设想将应用程序的目录更新内容用xml格式发送到感兴趣的聚会上。由于某些原因,有一个客户需要一种略微不同的格式。您可以用XmlAttributeOverrides类简单地自定义现有这套类即可,而不用写一整套不同的类来生成自定义格式。
就本例而言,使用清单12-1显示的Category类。但是在串行化时,您将在Category类将CategoryID字段重命名为ID,同时将其作为xml属性添加,而不是作为xml元素添加。
XmlAttrite 对象收集所有想加入给定元素的重写。在这种情况下,新建一个XmlAttributeAttribute对象后,可以修改属性名称,并将结果对象存储在重写容器的XmlAttribute属性中。
程序清单 12-8
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %> <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server"> void Page_Load(object sender, System.EventArgs e)
    void Page_Load(object sender, System.EventArgs e) {
    { string xmlFilePath = @"C:\Data\Category.xml";
        string xmlFilePath = @"C:\Data\Category.xml"; Category categoryObj = new Category();
        Category categoryObj = new Category(); categoryObj.CategoryID = 1;
        categoryObj.CategoryID = 1; categoryObj.CategoryName = "Beverages";
        categoryObj.CategoryName = "Beverages"; categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales";
        categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales"; 
        //Rename the CategoryID to ID and add it as an attribute
        //Rename the CategoryID to ID and add it as an attribute XmlAttributeAttribute categoryIDAttribute = new XmlAttributeAttribute();
        XmlAttributeAttribute categoryIDAttribute = new XmlAttributeAttribute(); categoryIDAttribute.AttributeName = "ID";
        categoryIDAttribute.AttributeName = "ID"; XmlAttributes attributesIdCol = new XmlAttributes();
        XmlAttributes attributesIdCol = new XmlAttributes(); attributesIdCol.XmlAttribute = categoryIDAttribute;
        attributesIdCol.XmlAttribute = categoryIDAttribute;         XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
        XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides(); attrOverrides.Add(typeof(Category), "CategoryID", attributesIdCol);
        attrOverrides.Add(typeof(Category), "CategoryID", attributesIdCol);
 //Rename the CategoryName to Name and add it as an element
        //Rename the CategoryName to Name and add it as an element XmlElementAttribute categoryNameElement = new XmlElementAttribute();
        XmlElementAttribute categoryNameElement = new XmlElementAttribute(); categoryNameElement.ElementName = "Name";
        categoryNameElement.ElementName = "Name"; XmlAttributes attributesNameCol = new XmlAttributes();
        XmlAttributes attributesNameCol = new XmlAttributes(); attributesNameCol.XmlElements.Add(categoryNameElement);
        attributesNameCol.XmlElements.Add(categoryNameElement); attrOverrides.Add(typeof(Category), "CategoryName", attributesNameCol);
        attrOverrides.Add(typeof(Category), "CategoryName", attributesNameCol);         
         XmlSerializer serializer = new XmlSerializer(typeof(Category), attrOverrides);
        XmlSerializer serializer = new XmlSerializer(typeof(Category), attrOverrides); TextWriter writer = new StreamWriter(xmlFilePath);
        TextWriter writer = new StreamWriter(xmlFilePath); // Serialize the Category and close the TextWriter
        // Serialize the Category and close the TextWriter serializer.Serialize(writer, categoryObj);
        serializer.Serialize(writer, categoryObj); writer.Close();
        writer.Close(); Response.Write("File written successfully");
        Response.Write("File written successfully"); }
    } </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml" >
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">
<head runat="server"> <title>Customizing XML Output at runtime using XmlAttributeOverrides</title>
    <title>Customizing XML Output at runtime using XmlAttributeOverrides</title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
    <div> 
     </div>
    </div> </form>
    </form> </body>
</body> </html>
</html>打开生成的Category.xml应看到下面代码:
 <?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?> <Category xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="1">
<Category xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="1"> <Name>Beverages</Name>
  <Name>Beverages</Name> <Description>Soft drinks, coffees, teas, beers, and ales</Description>
  <Description>Soft drinks, coffees, teas, beers, and ales</Description> </Category>
</Category>注意:
对于每个重写对象,需要一个独特的Xmlattribute对象。这就意味着如果试图重写两个元素,则需要创建两个不同的Xmlattribute对象,并将其体那家到XmlAttributeOverrides对象中。
3.用命名空间生成受限的名称
通常,应用程序需要将新信息添加到已存在的xml文档中,或者已有的xml文档组合起来。为了避免在这些场合中的冲突,WC3联盟标准化了xml命名空间。您可以将命名空间看作元素和属性的最后一个名称。
添加到由XmlSerializer生成的xml中的默认命名空间是xmlns:xsd="http://www.w3.org/2001/XMLSchema" 和 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 。通过创建XmlSerializerNamespaces对象并用一列命名空间和别名可以对默认的命名空间进行重写。
使用Category类
 using System;
using System; using System.Xml;
using System.Xml; using System.Xml.Serialization;
using System.Xml.Serialization;
 [XmlRoot(Namespace = "http://northwind.com/category")]
[XmlRoot(Namespace = "http://northwind.com/category")] public class Category
public class Category {
{ public long CategoryID;
    public long CategoryID; public string CategoryName;
    public string CategoryName; public string Description;
    public string Description; }
}程序清单12-9 使用XmlSerializerNamespaces生成受限的名称
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %> <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Xml" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server"> void Page_Load(object sender, System.EventArgs e)
    void Page_Load(object sender, System.EventArgs e) {
    { string xmlFilePath = @"C:\Data\Category.xml";
        string xmlFilePath = @"C:\Data\Category.xml"; Category categoryObj = new Category();
        Category categoryObj = new Category(); categoryObj.CategoryID = 1;
        categoryObj.CategoryID = 1; categoryObj.CategoryName = "Beverages";
        categoryObj.CategoryName = "Beverages"; categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales";
        categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales"; XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
        XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); namespaces.Add("cate", "http://northwind.com/category");
        namespaces.Add("cate", "http://northwind.com/category");        XmlSerializer serializer = new XmlSerializer(typeof(Category));
        XmlSerializer serializer = new XmlSerializer(typeof(Category)); TextWriter writer = new StreamWriter(xmlFilePath);
        TextWriter writer = new StreamWriter(xmlFilePath); //Serialize the Category and close the TextWriter
        //Serialize the Category and close the TextWriter serializer.Serialize(writer, categoryObj,namespaces);
        serializer.Serialize(writer, categoryObj,namespaces); writer.Close();
        writer.Close(); Response.Write("File written successfully");
        Response.Write("File written successfully");         }
    } 
 </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml" >
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">
<head runat="server"> <title>Using XmlSerializerNamespaces class to generate Qualified Names</title>
    <title>Using XmlSerializerNamespaces class to generate Qualified Names</title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
    <div> 
     </div>
    </div> </form>
    </form> </body>
</body> </html>
</html>删除xsd 和 xsi 声明
如果您以前曾经做过任何串行化,那么您一定会知道:当用XmlSerializer串行化类时将获得若干声明,这些声明作为结果xml的一部份,类似下面的输出:
<Category xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
正如您所见,xsd 和 xsi 命名空间声明被串行器放在输出结果中。要删除xsd 和 xsi 命名空间,需要创建一个空的XmlSerializerNamespaces类,并添加一个简单条目,指定一个空的命名空间前缀和命名空间url。代码如下:
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add("", "");
4.串行化集合
集合类与数组类似,但是其长度不需要固定,可以容纳非相关的类型,是不同使用场景的最佳选择。.NET Framework 提供了大量用于System.Collection命名空间的集合,如ArrayList、Dictionary、或Hashtable 等只是其中一部分。
您也可以串行化多个对象的图。要串行化集合或数组,也必须向XmlSerializer对象提供关于集合的类型和其中的内容的一个或几个类型。例如要串行化的对象是ArrayList而其中的内容是Category和Product对象时。XmlSerializer类为这样的可能性准备了一个构造函数----它期待包含类的类型号,以及描述一些类的类型数组:
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %> <%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="System.Collections" %> <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Xml" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server"> void Page_Load(object sender, System.EventArgs e)
    void Page_Load(object sender, System.EventArgs e) {
    { string xmlFilePath = @"C:\Data\ArrayList.xml";
        string xmlFilePath = @"C:\Data\ArrayList.xml"; Category categoryObj = new Category();
        Category categoryObj = new Category(); categoryObj.CategoryID = 1;
        categoryObj.CategoryID = 1; categoryObj.CategoryName = "Beverages";
        categoryObj.CategoryName = "Beverages"; categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales";
        categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales"; //Populate the products array
        //Populate the products array Product prodObj = new Product();
        Product prodObj = new Product(); prodObj.ProductID = 1;
        prodObj.ProductID = 1; prodObj.ProductName = "Chai";
        prodObj.ProductName = "Chai"; prodObj.QuantityPerUnit = "10 boxes x 20 bags";
        prodObj.QuantityPerUnit = "10 boxes x 20 bags"; prodObj.UnitPrice = "18";
        prodObj.UnitPrice = "18"; prodObj.UnitsInStock = 39;
        prodObj.UnitsInStock = 39; ArrayList list = new ArrayList();
        ArrayList list = new ArrayList(); list.Add(categoryObj);
        list.Add(categoryObj); list.Add(prodObj);
        list.Add(prodObj);         //Add all the types to the serializer
        //Add all the types to the serializer Type[] extraTypes = new Type[2];
        Type[] extraTypes = new Type[2]; extraTypes[0] = typeof(Category);
        extraTypes[0] = typeof(Category); extraTypes[1] = typeof(Product);
        extraTypes[1] = typeof(Product); XmlSerializer serializer = new XmlSerializer(typeof(ArrayList), extraTypes);
        XmlSerializer serializer = new XmlSerializer(typeof(ArrayList), extraTypes); TextWriter writer = new StreamWriter(xmlFilePath);
        TextWriter writer = new StreamWriter(xmlFilePath); // Serialize the ArrayList and close the TextWriter
        // Serialize the ArrayList and close the TextWriter serializer.Serialize(writer, list);
        serializer.Serialize(writer, list); writer.Close();
        writer.Close(); Response.Write("File written successfully");
        Response.Write("File written successfully");                  }
    } </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml" >
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">
<head runat="server"> <title>Serializing an ArrayList object</title>
    <title>Serializing an ArrayList object</title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
    <div>         </div>
    </div>         </form>
    </form> </body>
</body> </html>
</html>
然后可以创建一个流,并和以前一样串行化该流。
串行化自定义集合
XmlSerializer也可以处理自定义集合对象,只要这些对象实现这两个.NET Framework 的集合接口之一:IEnumerable 或 ICollection 。.NET Framework提供的所有集合将实现这些接口,因此您可以串行化或反串行化这些集合,而不必增加额外工作。
说明:
只要符合一些条件,像集合(实现ICollection接口的对象)这样的容器对象的内容将被自动串行化;Add方法必须采用简单的正行参数。除了选择适当的对象类型外,当然,您必须确保集合的内容本身符合xml串行化需求,需求如下:每个类必须提供一个默认的构造函数,您应该提供一种通过可用的公开成员或属性访问类中的方式。
 using System;
using System; using System.Collections;
using System.Collections; using System.Xml.Serialization;
using System.Xml.Serialization;
 public class CategoriesList
public class CategoriesList {
{ private ArrayList _categoriesList;
    private ArrayList _categoriesList;
 public CategoriesList()
    public CategoriesList() {
    { _categoriesList = new ArrayList();
        _categoriesList = new ArrayList();
 }
    }
 public Category[] Categories
    public Category[] Categories {
    { get
        get {
        { Category[] categories = new Category[_categoriesList.Count];
            Category[] categories = new Category[_categoriesList.Count]; _categoriesList.CopyTo(categories);
            _categoriesList.CopyTo(categories); return categories;
            return categories; }
        } set
        set {
        { if (value == null) return;
            if (value == null) return; Category[] categories = (Category[])value;
            Category[] categories = (Category[])value; _categoriesList.Clear();
            _categoriesList.Clear(); foreach (Category cate in categories)
            foreach (Category cate in categories) _categoriesList.Add(cate);
                _categoriesList.Add(cate); }
        } }
    }
 public int AddCategory(Category cate)
    public int AddCategory(Category cate) {
    { return _categoriesList.Add(cate);
        return _categoriesList.Add(cate); }
    } }
}程序清单12-11 串行化CategoriesList对象
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %> <%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="System.Collections" %> <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server"> void Page_Load(object sender, System.EventArgs e)
    void Page_Load(object sender, System.EventArgs e) {
    { string xmlFilePath = @"C:\Data\Categories.xml";
        string xmlFilePath = @"C:\Data\Categories.xml"; Category category1 = new Category();
        Category category1 = new Category(); category1.CategoryID = 1;
        category1.CategoryID = 1; category1.CategoryName = "Beverages";
        category1.CategoryName = "Beverages"; category1.Description = "Soft drinks, coffees, teas, beers, and ales";
        category1.Description = "Soft drinks, coffees, teas, beers, and ales"; Category category2 = new Category();
        Category category2 = new Category(); category2.CategoryID = 2;
        category2.CategoryID = 2; category2.CategoryName = "Condiments";
        category2.CategoryName = "Condiments"; category2.Description = "Sweet and savory sauces, relishes, spreads, and seasonings";
        category2.Description = "Sweet and savory sauces, relishes, spreads, and seasonings"; CategoriesList list = new CategoriesList();
        CategoriesList list = new CategoriesList(); list.AddCategory(category1);
        list.AddCategory(category1); list.AddCategory(category2);
        list.AddCategory(category2);    XmlSerializer serializer = new XmlSerializer(typeof(CategoriesList));
        XmlSerializer serializer = new XmlSerializer(typeof(CategoriesList)); TextWriter writer = new StreamWriter(xmlFilePath);
        TextWriter writer = new StreamWriter(xmlFilePath); //Serialize the Category and close the TextWriter
        //Serialize the Category and close the TextWriter serializer.Serialize(writer, list);
        serializer.Serialize(writer, list); writer.Close();
        writer.Close(); Response.Write("File written successfully");
        Response.Write("File written successfully");                 }
    } </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml" >
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">
<head runat="server"> <title>Serializing a Collection Object</title>
    <title>Serializing a Collection Object</title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
    <div> 
     </div>
    </div> </form>
    </form> </body>
</body> </html>
</html>产生的xml结果
 <?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?> <CategoriesList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CategoriesList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Categories>
  <Categories> <Category>
    <Category> <CategoryID>1</CategoryID>
      <CategoryID>1</CategoryID> <CategoryName>Beverages</CategoryName>
      <CategoryName>Beverages</CategoryName> <Description>Soft drinks, coffees, teas, beers, and ales</Description>
      <Description>Soft drinks, coffees, teas, beers, and ales</Description> </Category>
    </Category> <Category>
    <Category> <CategoryID>2</CategoryID>
      <CategoryID>2</CategoryID> <CategoryName>Condiments</CategoryName>
      <CategoryName>Condiments</CategoryName> <Description>Sweet and savory sauces, relishes, spreads, and seasonings</Description>
      <Description>Sweet and savory sauces, relishes, spreads, and seasonings</Description> </Category>
    </Category> </Categories>
  </Categories> </CategoriesList>
</CategoriesList>1.3 反串行化xml
要反串行化文件Category.xml(在前面的示例中创建的)中的Category对象,您可以直接打开文件流、初始XmlSerializer,并调用Deserialize。
程序清单12-12 将xml文件反串行化为对象
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %>
 <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server"> void Page_Load(object sender, System.EventArgs e)
    void Page_Load(object sender, System.EventArgs e) {
    { string xmlFilePath = @"C:\Category.xml";
        string xmlFilePath = @"C:\Category.xml"; XmlSerializer serializer = new XmlSerializer(typeof(Category));
        XmlSerializer serializer = new XmlSerializer(typeof(Category)); TextReader reader = new StreamReader(xmlFilePath);
        TextReader reader = new StreamReader(xmlFilePath); //Deserialize the Category and close the TextReader
        //Deserialize the Category and close the TextReader Category categoryObj = (Category)serializer.Deserialize(reader);
        Category categoryObj = (Category)serializer.Deserialize(reader); reader.Close();
        reader.Close(); Response.Write("CategoryID: " + categoryObj.CategoryID + "<br>");
        Response.Write("CategoryID: " + categoryObj.CategoryID + "<br>"); Response.Write("Category Name: " + categoryObj.CategoryName + "<br>");
        Response.Write("Category Name: " + categoryObj.CategoryName + "<br>"); Response.Write("Category Description: " + categoryObj.Description + "<br>");
        Response.Write("Category Description: " + categoryObj.Description + "<br>"); }
    } </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">
<head runat="server"> <title>Simple XML Deserialization</title>
    <title>Simple XML Deserialization</title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
        <div> </div>
        </div> </form>
    </form> </body>
</body> </html>
</html>5.处理XmlSerializer引发的事件
 如果输入流不符合预期的形式,那么反串行化过程将试图尽最大能力恢复,但是当过程完成时,作为结果的一个或多个对象可以设置为空值,为了帮助处理这些情况,XmlSerializer类发布了4个您可以遇到的事件。
 
XmlSerializer类的事件
UnknownAttribute  当 XmlSerializer 在反序列化过程中遇到未知类型的 XML 属性 (Attribute) 时发生。  
UnknownElement  当 XmlSerializer 在反序列化过程中遇到未知类型的 XML 元素时发生。  
UnknownNode  当 XmlSerializer 在反序列化过程中遇到未知类型的 XML 节点时发生。  
UnreferencedObject  在反序列化 SOAP 编码的 XML 流的过程中发生,此时 XmlSerializer 遇到未使用(或未引用)的识别类型。 
通过创建适当的委托,可捕获这些事件。
                                     程序清单12-13 处理由XmlSerializer类引发的事件
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %>
 <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Xml" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server"> void Page_Load(object sender, System.EventArgs e)
    void Page_Load(object sender, System.EventArgs e) {
    { string xmlFilePath = @"C:\Data\Category.xml";
        string xmlFilePath = @"C:\Data\Category.xml"; XmlSerializer serializer = new XmlSerializer(typeof(Category));
        XmlSerializer serializer = new XmlSerializer(typeof(Category)); serializer.UnknownElement += new XmlElementEventHandler(XmlSerializer_UnknownElement);
        serializer.UnknownElement += new XmlElementEventHandler(XmlSerializer_UnknownElement); TextReader reader = new StreamReader(xmlFilePath);
        TextReader reader = new StreamReader(xmlFilePath); //Deserialize the Category and close the TextReader
        //Deserialize the Category and close the TextReader Category categoryObj = (Category)serializer.Deserialize(reader);
        Category categoryObj = (Category)serializer.Deserialize(reader); reader.Close();
        reader.Close(); Response.Write("<b>Result of Deserialization:" + "</b><br>");
        Response.Write("<b>Result of Deserialization:" + "</b><br>"); Response.Write("CategoryID: " + categoryObj.CategoryID + "<br>");
        Response.Write("CategoryID: " + categoryObj.CategoryID + "<br>"); Response.Write("Category Name: " + categoryObj.CategoryName + "<br>");
        Response.Write("Category Name: " + categoryObj.CategoryName + "<br>"); }
    }
 void XmlSerializer_UnknownElement(object sender, XmlElementEventArgs e)
    void XmlSerializer_UnknownElement(object sender, XmlElementEventArgs e) {
    { Category categoryObj = (Category)e.ObjectBeingDeserialized;
        Category categoryObj = (Category)e.ObjectBeingDeserialized; Response.Write("<b>Unknown Element:" + "</b><br>");
        Response.Write("<b>Unknown Element:" + "</b><br>"); Response.Write("Unknown Element Name: " + e.Element.Name + "<br>");
        Response.Write("Unknown Element Name: " + e.Element.Name + "<br>"); Response.Write("Unknown Element Value: " + e.Element.InnerText + "<br><br>");
        Response.Write("Unknown Element Value: " + e.Element.InnerText + "<br><br>"); }
    }
 </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">
<head runat="server"> <title>Handling Events Raised by XmlSerializer </title>
    <title>Handling Events Raised by XmlSerializer </title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
        <div> </div>
        </div> </form>
    </form> </body>
</body> </html>
</html>该代码假定Category类的声明如下。
public class Category
{
public long CategoryID;
public string CategoryName;
}
正如前面所见,前面示例中用到的Description字段在Category类中消失了。作为程序清单12-13中的xml输入文档使用的xml文件内容如下:
 <?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?> <Category xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Category xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <CategoryID>1</CategoryID>
  <CategoryID>1</CategoryID> <Name>Beverages</Name>
  <Name>Beverages</Name> <Description>Soft drinks, coffees, teas, beers, and ales</Description>
  <Description>Soft drinks, coffees, teas, beers, and ales</Description> </Category>
</Category>输出结果如下:
Unknown Element:
Unknown Element Name: Description
Unknown Element Value: Soft drinks, coffees, teas, beers, and ales
Result of Deserialization:
CategoryID: 1
Category Name: Beverages
注意:XmlElementEventArgs对象提供了名为ObjectBeingDeserialized的属性,使您可以在反串行化期间引用Category对象。当您想执行一些基于对象将填充的内容时,非常有用。
6.用反串行化映射SQL Server 数据
xml 文档
 <Contacts>
<Contacts> <ContactID>2</ContactID>
  <ContactID>2</ContactID> <FirstName>Catherine</FirstName>
  <FirstName>Catherine</FirstName> <MiddleName>R.</MiddleName>
  <MiddleName>R.</MiddleName> <LastName>Abel</LastName>
  <LastName>Abel</LastName> <EmailAddress>catherine0@adventure-works.com</EmailAddress>
  <EmailAddress>catherine0@adventure-works.com</EmailAddress> </Contacts>
</Contacts>程序清单12-4 Contace类
 using System;
using System; using System.Xml;
using System.Xml; using System.Xml.Serialization;
using System.Xml.Serialization;

 [XmlRoot("Contacts")]
[XmlRoot("Contacts")] public class Contact
public class Contact {
{ public string ID;
    public string ID; public string FirstName;
    public string FirstName; public string MiddleName;
    public string MiddleName; public string LastName;
    public string LastName; }
}程序清单12-5 使用Contace对象将Contact数据映射到AdventureWorks数据库中
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %>
 <%@ Import Namespace="System.Collections" %>
<%@ Import Namespace="System.Collections" %> <%@ Import Namespace="System.Web.Configuration" %>
<%@ Import Namespace="System.Web.Configuration" %> <%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="System.Data.SqlClient" %> <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Xml" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server"> void Page_Load(object sender, System.EventArgs e)
    void Page_Load(object sender, System.EventArgs e) {
    { Contact cont;
        Contact cont; //Rename the ContactID to ID element and add it as an attribute
        //Rename the ContactID to ID element and add it as an attribute XmlElementAttribute contIDElement = new XmlElementAttribute();
        XmlElementAttribute contIDElement = new XmlElementAttribute(); contIDElement.ElementName = "ContactID";
        contIDElement.ElementName = "ContactID"; XmlAttributes attributesIdCol = new XmlAttributes();
        XmlAttributes attributesIdCol = new XmlAttributes(); attributesIdCol.XmlElements.Add(contIDElement);
        attributesIdCol.XmlElements.Add(contIDElement); XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
        XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides(); attrOverrides.Add(typeof(Contact), "ID", attributesIdCol);
        attrOverrides.Add(typeof(Contact), "ID", attributesIdCol); string connString =
        string connString = WebConfigurationManager.ConnectionStrings["adventureWorks"].
          WebConfigurationManager.ConnectionStrings["adventureWorks"]. ConnectionString;
          ConnectionString; SqlConnection sqlConn = new SqlConnection(connString);
        SqlConnection sqlConn = new SqlConnection(connString); sqlConn.Open();
        sqlConn.Open(); //Instantiate the SqlCommand object and pass the query to be executed
        //Instantiate the SqlCommand object and pass the query to be executed SqlCommand sqlCommand = new SqlCommand("Select ContactID," +
        SqlCommand sqlCommand = new SqlCommand("Select ContactID," + "FirstName, MiddleName, LastName, EmailAddress from Person.Contact " +
          "FirstName, MiddleName, LastName, EmailAddress from Person.Contact " + "as Contacts where ContactID = 2 for xml auto, elements", sqlConn);
          "as Contacts where ContactID = 2 for xml auto, elements", sqlConn); XmlReader reader = sqlCommand.ExecuteXmlReader();
        XmlReader reader = sqlCommand.ExecuteXmlReader(); XmlSerializer serializer = new XmlSerializer(typeof(Contact),
        XmlSerializer serializer = new XmlSerializer(typeof(Contact), attrOverrides);
          attrOverrides); serializer.UnknownElement += new
        serializer.UnknownElement += new XmlElementEventHandler(XmlSerializer_UnknownElement);
          XmlElementEventHandler(XmlSerializer_UnknownElement); if (serializer.CanDeserialize(reader))
        if (serializer.CanDeserialize(reader)) {
        { cont = (Contact)serializer.Deserialize(reader);
            cont = (Contact)serializer.Deserialize(reader); Response.Write("<b>Result of Deserialization:" + "</b><br>");
            Response.Write("<b>Result of Deserialization:" + "</b><br>"); Response.Write("ID: " + cont.ID + "<br>");
            Response.Write("ID: " + cont.ID + "<br>"); Response.Write("First Name: " + cont.FirstName + "<br>");
            Response.Write("First Name: " + cont.FirstName + "<br>"); Response.Write("Middle Name: " + cont.MiddleName + "<br>");
            Response.Write("Middle Name: " + cont.MiddleName + "<br>"); Response.Write("Last Name: " + cont.LastName + "<br>");
            Response.Write("Last Name: " + cont.LastName + "<br>"); }
        } else
        else Response.Write("Cannot serialize data");
            Response.Write("Cannot serialize data"); }
    }
 void XmlSerializer_UnknownElement(object sender, XmlElementEventArgs e)
    void XmlSerializer_UnknownElement(object sender, XmlElementEventArgs e) {
    { Response.Write("<b>Unknown Element:" + "</b><br>");
        Response.Write("<b>Unknown Element:" + "</b><br>"); Response.Write("Unknown Element Name: " + e.Element.Name + "<br>");
        Response.Write("Unknown Element Name: " + e.Element.Name + "<br>"); Response.Write("Unknown Element Value: " + e.Element.InnerText +
        Response.Write("Unknown Element Value: " + e.Element.InnerText + "<br><br>");
          "<br><br>"); }
    } </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server">
<head id="Head1" runat="server"> <title>Mapping Contacts Data in AdventureWorks Database with the Customer Object </title>
    <title>Mapping Contacts Data in AdventureWorks Database with the Customer Object </title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
        <div> </div>
        </div> </form>
    </form> </body>
</body> </html>
</html>输出结果:
Unknown Element:
Unknown Element Name: EmailAddress
Unknown Element Value: catherine0@adventure-works.com
Result of Deserialization:
ID: 2
First Name: Catherine
Middle Name: R.
Last Name: Abel
1.4 泛型和XML串行化
 CLR使用.NET Framwork2.0 大大增强表达力,泛型类型可增加对运行时的完全支持。xml串行化已延伸到串行化和反串行化的通用类型。
现分析一下泛型类型的代码,见程序清单12-16
 using System;
using System; using System.Collections;
using System.Collections; using System.Xml.Serialization;
using System.Xml.Serialization;
 [XmlRoot("NameValuePair")]
[XmlRoot("NameValuePair")] public class NameValue<KeyType, ValueType>
public class NameValue<KeyType, ValueType> {
{ private KeyType _key;
    private KeyType _key; private ValueType _value;
    private ValueType _value;
 public NameValue()
    public NameValue() {
    { }
    } public ValueType Value
    public ValueType Value {
    { get
        get {
        { return _value;
            return _value; }
        } set
        set {
        { _value = value;
            _value = value; }
        } }
    } public KeyType Key
    public KeyType Key {
    { get
        get {
        { return _key;
            return _key; }
        } set
        set {
        { _key = value;
            _key = value; }
        } }
    } }
}程序清单12-17 用泛型执行串行化和反串行化
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %>
 <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server"> 
     private string _xmlFilePath = @"C:\Data\NameValue.xml";
    private string _xmlFilePath = @"C:\Data\NameValue.xml";
 void Serialize(object sender, EventArgs e)
    void Serialize(object sender, EventArgs e) {
    { NameValue<int, string> nameVal = new NameValue<int, string>();
        NameValue<int, string> nameVal = new NameValue<int, string>(); nameVal.Key = 1;
        nameVal.Key = 1; nameVal.Value = "Manufacturing";
        nameVal.Value = "Manufacturing"; XmlSerializer serializer = new XmlSerializer(typeof(NameValue<int, string>));
        XmlSerializer serializer = new XmlSerializer(typeof(NameValue<int, string>)); TextWriter writer = new StreamWriter(_xmlFilePath);
        TextWriter writer = new StreamWriter(_xmlFilePath); //Serialize the NameValue object and close the TextWriter
        //Serialize the NameValue object and close the TextWriter serializer.Serialize(writer, nameVal);
        serializer.Serialize(writer, nameVal); writer.Close();
        writer.Close(); lblResult.Text = "File written successfully";
        lblResult.Text = "File written successfully"; }
    }
 void Deserialize(object sender, EventArgs e)
    void Deserialize(object sender, EventArgs e) {
    { XmlSerializer serializer = new XmlSerializer(typeof(NameValue<int, string>));
        XmlSerializer serializer = new XmlSerializer(typeof(NameValue<int, string>)); TextReader reader = new StreamReader(_xmlFilePath);
        TextReader reader = new StreamReader(_xmlFilePath); //Deserialize the Category and close the TextReader
        //Deserialize the Category and close the TextReader NameValue<int, string> nameVal = (NameValue<int, string>)serializer.Deserialize(reader);
        NameValue<int, string> nameVal = (NameValue<int, string>)serializer.Deserialize(reader); reader.Close();
        reader.Close(); lblResult.Text = "Key : " + nameVal.Key + "<br>";
        lblResult.Text = "Key : " + nameVal.Key + "<br>"; lblResult.Text += "Value: " + nameVal.Value;
        lblResult.Text += "Value: " + nameVal.Value;
 }
    }        
 </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">
<head runat="server"> <title>Using Generics for Serialization and Deserialization</title>
    <title>Using Generics for Serialization and Deserialization</title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
        <div> <asp:Button runat="Server" ID="btnSerialize" OnClick="Serialize" Text="Serialize" />
            <asp:Button runat="Server" ID="btnSerialize" OnClick="Serialize" Text="Serialize" /> <asp:Button runat="Server" ID="btnDeserialize" OnClick="Deserialize" Text="Deserialize" />
            <asp:Button runat="Server" ID="btnDeserialize" OnClick="Deserialize" Text="Deserialize" /> <br />
            <br /> <br />
            <br /> <asp:Label runat="Server" ID="lblResult" Height="21px" Width="351px" />
            <asp:Label runat="Server" ID="lblResult" Height="21px" Width="351px" /> </div>
        </div> </form>
    </form> </body>
</body> </html>
</html>串行化泛型集合
除了创建简单的泛型类型外,您还可以创建强类型化泛型集合,这些集合的类型安全和性能比非泛型的强类型化集合更好。System.Collection.Generic命名空间包含若干用于定义泛型集合的接口和类。看一下下列代码,理解如何用List类创建强类型化的类别集合对象。
List<Category> list = new List<Category>();
程序清单12-18 Serializing Typed Generics Collections
 <%@ Page Language="C#" %>
<%@ Page Language="C#" %>
 <%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Collections.Generic" %> <%@ Import Namespace="System.Xml.Serialization" %>
<%@ Import Namespace="System.Xml.Serialization" %>
 <script runat="server">
<script runat="server">    void Page_Load(object sender, EventArgs e)
    void Page_Load(object sender, EventArgs e) {
    { string xmlFilePath = @"C:\Data\GenericCollections.xml";
        string xmlFilePath = @"C:\Data\GenericCollections.xml"; List<Category> list = new List<Category>();
        List<Category> list = new List<Category>(); Category categoryObj = new Category();
        Category categoryObj = new Category(); categoryObj.CategoryID = 1;
        categoryObj.CategoryID = 1; categoryObj.CategoryName = "Beverages";
        categoryObj.CategoryName = "Beverages"; categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales";
        categoryObj.Description = "Soft drinks, coffees, teas, beers, and ales"; list.Add(categoryObj);
        list.Add(categoryObj); XmlSerializer serializer = new XmlSerializer(typeof(List<Category>));
        XmlSerializer serializer = new XmlSerializer(typeof(List<Category>)); TextWriter writer = new StreamWriter(xmlFilePath);
        TextWriter writer = new StreamWriter(xmlFilePath); //Serialize the Collection object and close the TextWriter
        //Serialize the Collection object and close the TextWriter serializer.Serialize(writer, list);
        serializer.Serialize(writer, list); writer.Close();
        writer.Close(); Response.Write("File written successfully");
        Response.Write("File written successfully"); }
    } </script>
</script>
 <html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">
<head runat="server"> <title>Serializing Typed Generics Collections</title>
    <title>Serializing Typed Generics Collections</title> </head>
</head> <body>
<body> <form id="form1" runat="server">
    <form id="form1" runat="server"> <div>
        <div> </div>
        </div> </form>
    </form> </body>
</body> </html>
</html>
 
                    
                


 
                
            
         
 浙公网安备 33010602011771号
浙公网安备 33010602011771号