代码改变世界

WCF 第六章 序列化与编码之XmlSerializer

2010-12-16 18:29  DanielWise  阅读(3668)  评论(2编辑  收藏  举报

XmlSerializer 是WCF中可以用来序列化的第三种方法。XmlSerializer 是已经被.NET2.0 架构内建支持的一个序列化方法。使用XmlSerializer有好几个优势,包括对已有.NET类型的支持,与ASP.NET Web 服务的兼容,和改变XML输出的能力。

  WCF支持XmlSerializer以便于它可以与已有的类型一起使用,而DataContractSerializer是特别用于新类型的。对已有类型的支持通常是对已有的应用程序或者那些你没有源码或者你不能重编译的你应用程序来支持DataContract序列化的第三方组件。XmlSerializer也是使用ASP.NET Web 服务使用的序列化方法。这意味着XmlSerializer可以用来帮助将ASP.NET Web 服务转换到WCF中。最后, XmlSerializer对序列化XML的输出提供更多控制并可以用在那些DataContractSerializer不适合对序列化XML形状进行改变的场景中。

  有三个适合使用XmlSerializer 的场景。第一个是依赖默认序列化。XmlSerializer 需要一个公共构造函数可以序列化任何公共字段和/或公共可读/可写属性。这是假定你的类可以通过使用一个默认构造函数并设置合适的字段和属性创建一个类的实例来重新组成。尽管很简单,除非你设计你的类支持序列化方法,否则这个方法几乎不会工作。它也意味着如果你不将一个类的内部属性暴露给外部世界那么你不能对它们进行序列化。第二个方法是使用[XmlElement]和[XmlAttribute]属性来标记公共字段和公共可读/可写属性。这些属性以及更多属性用来控制XML结果,它们可以在System.Xml.Serialization 命名空间中找到。这个属性可以用来控制公共字段和公共可读/可写属性在XML中的表示形式。尽管简单,这个方法仍会限制你如何序列化你的对象并可能强制你暴露那些你只想暴露给你自己类的构造函数的内部数据结构。第三种实现是使用IXmlSerializable接口使用XmlSerializer来完成自定义序列化。这种方法用来完成自定义序列化过程。

  接下来我们将在这一章查看使用XmlSerializer的自定义序列化。目前为止我们我们将关注最简单的使用XmlSerializer的例子。列表6.8 使用将列表6.1中的Employee类去掉[DataContract]或者[DataMember]使其不支持DataContractSerializer而支持XmlSerializer的同样的代码。需要一个默认的构造函数。

列表6.8 使用XmlSerializer 的Employee类

 [DataContract]
    public class Employee
    {
        private int employeeID;
        private string firstName;
        private string lastName;

        public Employee()
        {
        }

        public Employee(int employeeID, string firstName, string lastName)
        {
            this.employeeID = employeeID;
            this.firstName = firstName;
            this.lastName = lastName;
        }

        [DataMember]
        public int EmployeeID
        {
            get { return employeeID; }
            set { employeeID = value; }
        }

        [DataMember]
        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }

        [DataMember]
        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }
        }
    }

  列表6.9 显示了如何使用XmlSerializer序列化Employee实例

列表6.9 使用XmlSerializer 序列化

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;

namespace EssentialWCF
{
    class Program
    {
        static void Main(string[] args)
        {
            Employee e = new Employee(101, "Daniel", "Dong");
            FileStream writer = new FileStream("sample.xml", FileMode.Create);
            XmlSerializer ser = new XmlSerializer(typeof(Employee));
            ser.Serialize(writer, e);
            writer.Close();
        }
    }
}

  XmlSerializer的输出在列表6.10显示。注意输出与DataContractSerializer的结果类似。两个序列化基础结构输出的XML看起来很像。最大的不同没有显示。XmlSerializer不支持像DataContractSerializer支持的那么多类型但是它允许对结果XML更大的控制。

列表6.10 使用XmlSerializer的序列化的Employee类

<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <EmployeeID>101</EmployeeID>
  <FirstName>Daniel</FirstName>
  <LastName>Dong</LastName>
</Employee>

  列表6.8显示的Employee 类没有使用XmlSerializer序列化。[XmlSerializerFormat]属性可以用来定义一个服务契约,操作契约或者服务的属性来指导WCF使用XmlSerializer。列表6.11在一个服务契约上使用[XmlSerializerFormat]属性来指导WCF使用XmlSerializer。如果你正在使用XmlSerializer暴露任何契约你将想应用[XmlSerializerFormat]属性。这么做会指导Visual Studio 和svcutil.exe 工具生成可以依赖XmlSerializer的代理。不适用这个属性的话你需要使用svcutil.exe /Serializer:XmlSerializer 标识来生成代理。

提示 DataContractFormat属性

对应的,DataContractSerializer 也有一个与[XmlSerializerFormat]一样的属性,称作[DataContractFormat].WCF默认使用DataContractSerializer,所以没有任何需要使用这个属性的理由。

列表6.11 使用XmlSerializerFormat属性

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace EssentialWCF
{
    [ServiceContract]
    [XmlSerializerFormat]
    public interface IEmployeeInformation
    {
        [OperationContract]
        List<Employee> GetEmployees();
    }
}