如何在数据协定中缩减文档

posted at 2020.12.23 04:17 by Administrator

数据协定是一种约定,它要求参与协定的类型以及其成员结构必须匹配,但类型以及成员名称不一定相同。假设A类的协定名称为user_a,P1属性的协定名称为pop_1,P2属性的协定名称为pop_2。用A类的实例序列化之后生成的数据去填充B类的实例,虽然B类的两个属性分别为V1V2,,但是它所使用的数据协定名称与A类相同,此时是可以顺利进行反序列化的,因为它们都符合数据协定的要求。

数据协定最大的作用是在网络传输中保持数据模型的统一,即使数据的发送方与接收方声明了不同的类型,只要双方遵守数据协定,就可以完成序列化与反序列化。

  数据协定在类型定义上应当使用DataContractAttributeDataMemberAttribute类只应用于类型成员上(一般是字段和属性)。

数据协定也可以进行自定义。DataContractAttribute类和DataMemberAttribute类都公开了Name属性,该属性的作用是改变协定的默认名称(默认名称与类型名称相同)。

有时候并不需要一个类型中所有的成员(属性与字段)都参与序列化,要阻止某个成员被序列化,需要在成员定义是应用IgnoreDataMemberAttribute 

DataContractSerializer 类默认将数据协定以XML格式序列化,若需要序列化JSON格式,就得使用DataContractJsonSerializer类(位于System.Runtime.Serialization.Json命名空间),该类的使用方法与 DataContractSerializer类是一样的,只是输出的数据格式不同而已。

一般会按照以下规则来序列化数据协定的成员。

(1)如果数据协定类型具有继承关系,那么基类成员会优先进行序列化,然后再处理派生类的成员。

(2)如果设置了DataMemberAttribute.Order属性,将按照该顺序进行处理。否则,将按照字母顺序排序。

最令人激动人心的是,DataContractSerializerSettings类的PreserveObjectReferences属性为保留引用选项,将它设置为true,可以大量缩减文档的长度。

主要原理是,在开启保留实例引用选项后,在序列化的时候会为每个实例分配一个id,以保证每个实例在序列化时只生成一次。如果某个实例被多个成员引用,那么只有该实例第一次出现时才会填充数据,随后对该实例的引用都使用为实例所分配的id

下面举例说明:

步骤1:新建一个控制台应用程序项目。

步骤2:声明两个类,它们都是数据协定,并且OrderInfo类的DetailData属性引用OrderDetail的实例。

    [DataContract]

    public class OrderDetails

    {

        [DataMember]

        public string ContactName { get; set; }

        [DataMember]

        public decimal Price { get; set; }

        [DataMember]

        public int Quantity { get; set; }

        [DataMember]

        public float Weight { get; set; }

    } 

    [DataContract]

    public class OrderInfo

    {

        [DataMember]

        public int OrderNo { get; set; }

        [DataMember]

        public DateTime BuildTime { get; set; }

        [DataMember]

        public OrderDetails DetailsData { get; set; }

}

步骤3:执行序列化。

            using (FileStream fs = File.Open("data.xml", FileMode.Create))

            {

                OrderDetails dtl = new OrderDetails

                {

                    ContactName = "Fish",

                    Price = 3.15M,

                    Quantity = 12,

                    Weight = 17.5f

                };

                OrderInfo[] ords =

                {

                    new OrderInfo

                    {

                        OrderNo = 1,

                        BuildTime = new DateTime(2018, 3, 27),

                        DetailsData = dtl

                    },

                    new OrderInfo

                    {

                        OrderNo = 2,

                        BuildTime = new DateTime(2018, 9, 2),

                        DetailsData = dtl

                    }

                };

                DataContractSerializer sz = new DataContractSerializer(ords.GetType());

                sz.WriteObject(fs, ords);

            }

在未开启引用保留选项时,序列化后得到的XML文档如下.

  <ArrayOfOrderInfo xmlns="…" xmlns:i="…">

  <OrderInfo>

    <BuildTime>2018-03-27T00:00:00</BuildTime>

    <DetailsData>

      <ContactName>Fish</ContactName>

      <Price>3.15</Price>

      <Quantity>12</Quantity>

      <Weight>17.5</Weight>

    </DetailsData>

    <OrderNo>1</OrderNo>

  </OrderInfo>

  <OrderInfo>

    <BuildTime>2018-09-02T00:00:00</BuildTime>

    <DetailsData>

      <ContactName>Fish</ContactName>

      <Price>3.15</Price>

      <Quantity>12</Quantity>

      <Weight>17.5</Weight>

    </DetailsData>

    <OrderNo>2</OrderNo>

  </OrderInfo>

  </ArrayOfOrderInfo>

 可以看出,OrderDetails实例的各个属性值被写入了两次。

  步骤4:对序列化的代码进行修改,开启保留引用选项。

            using (FileStream fs = File.Open("data.xml", FileMode.Create))

            {

                … …

                DataContractSerializerSettings settings = new DataContractSerializerSettings();

                settings.PreserveObjectReferences = true;

                DataContractSerializer sz = new DataContractSerializer(ords.GetType(),settings);

                sz.WriteObject(fs, ords);

            }

步骤5:运行应用程序,保留对象引用后生成的XML文档如下。

  此次OrderDetails实例的各个属性值只写入了一次,第二次是通过id引用的,即上述XML文档中的z:Ref=”3”

Tags: , , , , , ,

IT技术

添加评论

  Country flag

biuquote
  • 评论
  • 在线预览
Loading