代码改变世界

WCF 第六章 序列化与编码 比较WCF序列化选项

2010-12-15 17:31  DanielWise  阅读(933)  评论(0编辑  收藏  举报

使用WCF有很多种方式来序列化对象。确定使用哪种方法来序列化取决于一系列因素。这些因素包括你是否想要与契约共享类型,支持现有的.NET类型,保留引用以及更多。

DataContractSerializer

WCF中默认的序列化方法是DataContractSerializer.这个类存在于System.Runtime.Serialization命名空间里。DataContractSerializer是用来支持基于XSD元数据的契约共享的。它将公共语言运行时(CLR)类型映射成XSD定义的类型。这意味着XSD是可以用来在两个应用程序间交换数据的公共元数据。例如,你可以使用XSD在一个.NET应用程序和一个Java应用程序间交换数据。我们使用一个字符串来举个例子。

12-15-2010 3-21-21 PM

    图片6.2 XSD类型

注意只是XSD类型在一个服务端和一个客户端交换,而不是类型信息。所以在图片6.2中,System.String或者java.lang.String的概念不作为消息交换的一部分。这允许任何一边将XSD类型映射为它们自己环境中的特殊类型。这对于初始类型是可以很好工作的。复杂类型会变成初始类型的一个扩展。所以我们该如何描述使用DataContractSerializer来将一个.NET CLR类型映射为一个XSD元数据?

  正如在第二章描述的那样,[DataContract]属性可以用来标记一个类型是可序列化的。成员和属性可以使用[DataMember]属性来标记为数据契约的一部分。当开发人员定义类型是如何被序列化时这是一个非常选择进入的场景。这意味着契约是显式的,与XmlSerializer的非常选择退出模式不同。列表6.1 显示了一个复杂类型的例子,Employee, 它使用了DataContractSerializer. 我们将使用Employee类型来检查元数据以及使用DataContractSerializer 的序列化输出。这将形成与WCF内部的其他序列化方法比较的基础。

列表6.1 使用DataContractSerialization的Employee类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

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

        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.1显示的Employee复杂类型由列表6.2中的XSD元数据表示

列表6.2 Employee XSD 元数据

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://schemas.datacontract.org/2004/07/Employee" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/Employee" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:complexType name="Employee">
    <xs:sequence>
      <xs:element minOccurs="0" name="EmployeeID" type="xs:int" />
      <xs:element minOccurs="0" name="FirstName" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="LastName" nillable="true" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:element name="Employee" nillable="true" type="tns:Employee" />
</xs:schema>

列表6.3显示了Employee类的元数据是如何导出的。

列表6.3 导出XSD元数据

    class Program
    {
        static void Main(string[] args)
        {
            XsdDataContractExporter xsdexp = new XsdDataContractExporter();
            xsdexp.Options = new ExportOptions();
            xsdexp.Export(typeof(Employee));

            //Write out exported schema to a file
            using (FileStream fs = new FileStream("sample.xsd", FileMode.Create))
            {
                foreach (XmlSchema sch in xsdexp.Schemas.Schemas())
                {
                    sch.Write(fs);
                }
            }
        }
    }

  为了完成与其他序列化结构比较的基础我们还要做最后一个任务,使用DataContractSerializer来序列化一个Employee实例。列表6.4显示了这是如何完成的。

列表6.4 使用DataContractSerializer序列化

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

  Employee类使用DataContractSerializer的序列化输出结果在列表6.5 中显示。

列表6.5 使用DataContractSerializer的被序列化的Employee类

<Employee xmlns="http://schemas.datacontract.org/2004/07/EssentialWCF" 
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <EmployeeID>101</EmployeeID>
  <FirstName>Daniel</FirstName>
  <LastName>Dong</LastName>
</Employee>