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

posted at 2020.12.23 06: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技术

Add comment

  Country flag

biuquote
微笑得意调皮害羞酷大笑惊讶发呆喜欢可怜尴尬闭嘴噘嘴皱眉伤心抓狂呕吐坏笑漫骂发怒
Loading