天天看点

WCF 序列化与反序列化复杂类型(DataContractSerializer)

.net的类型可以分为两种:声明类型和真实类型。我们提倡面向接口的编程,对象的真实类型往往需要在运行时才能确定,在编程的时候往往只需要指明类型的声明类型,比如类型实现的接口或者抽象类。当我们使用基于接口或者抽象类创建的datacontractserializer去序列化一个实现了该接口或者继承该抽象类的实例的时候,往往会因为对对象的真实类型无法识别造成不能正常地序列化。

 现在,我们定义两个带数据协定的类——actioninfo和actionparameterinfo:

在代码中添加以下代码填充实体类:

      测试序列化:

生成的xml如下:

  从xml看到:

datacontractserializer在默认的情况下采用了如下的序列化规则。

1、xml的根节点名称为数据契约类型的名称。

2、默认的命名空间采用的格式为  http://schemas.datacontract.org/2004/07/datacontractserializerdemo (数据契约类型的命名空间)。

3、只有显示地应用了datamemberattributue特性的字段或属性才能作为数据成员参与序列化。

4、所有数据成员均以xml元素的形式被序列化。

5、序列化后数据成员在xml中的次序采用这样的规则:父类数据成员在前,子类数据成员在后;定义在同一个类型中的数据成员按照字母排序。

如果默认序列化后的xml结构不能满足我们的需求,则可以通过datacontractattribute和datamenmberattribute这两个特性对其进行修正。在下面我们通过datacontractattribute特性设置了数据契约的名称和命名空间,通过datamenmberattribute特性的name属性为name和birthday两个属性设置不同于属性名称的数据成员名称,并通过order控制数据成员的先后次序。

   修改actionparameterinfo类:

再次序列化,xml结构如下:

有木有发现datamember中name与order的作用啊

WCF 序列化与反序列化复杂类型(DataContractSerializer)

        小注:

对于一些比较复杂的类型无法序列化、反序列化(不能识别类型)的时候,就得考虑使用knowntypeattribute来标注可能涉及到的外部类型,但如果遇到像泛型这些较为复杂的类型,就要考虑在带数据协定的类中添加一个静态方法,该方法返回type 的ienumerable,一般是type[]就可以了,而在knowntypeattribute的构造函数中使用这个方法的名字。

在该demo中将actioninfo修改为如下形式(即去掉static type[] getknowtypes()函数,直接标识属性类型)也是可以正常序列化反序列化的:

修改实体类后的序列化xml如下:

  那可不可以去掉knowntype标识呢?答案是不可以的。

那么在actioninfo类中是否可以定义两个已知类型呢?

经过测试验证,不能再同一个类中定义两个已知类型,比如:

WCF 序列化与反序列化复杂类型(DataContractSerializer)

同时在类上标识:

WCF 序列化与反序列化复杂类型(DataContractSerializer)

错误信息如下:

但是对于同一个类型,在一个类中可以有多个属性,比如:

WCF 序列化与反序列化复杂类型(DataContractSerializer)

填充实体类代码如下:

序列化之后的xml如下:

如果就是有多个复杂属性如何处理呢?

铛铛==》

        修改actioninfo类为:

      填充实体的代码如下:

       序列化之后的结果为:

           可见,可以通过多个knowntype标识来实现同一个数据契约中多个复杂类型的序列化与反序列化。

此处是以两个字典类型来验证的,其实不管是list还是字典都可以通过:多个knowntype标识来实现同一个数据契约中多个复杂类型的序列化与反序列化。 

knowntype标识类简洁处理方式(这种方式不需要在类上标识knowntype):

       然后调用:

         即可

  datacontractjsonserializer的用法与datacontractserializer类似,只是两者对于实体类序列化后的存储形式不一样,仅此而已。

<a target="_blank" href="http://blog.csdn.net/jiankunking/article/details/48444973">c# wcf datacontractserializer 类</a>

小注:

如果序列化list&lt;baseclass&gt;即需要序列化一个由baseclass类及其子类组成的集合的时候,需要在子类基类上加上标识:

在反序列化的时候,调用:

 传入子类基类的的type。

参考文章:

<a target="_blank" href="http://www.cnblogs.com/meteorseed/archive/2012/05/13/2477514.html">wcf学习笔记——对象序列化</a>

<a target="_blank" href="http://blog.csdn.net/tcjiaan/article/details/8198716">传说中的wcf(6):数据协定(b)</a>

<a target="_blank" href="http://www.tuicool.com/articles/ujveyv">序列化和反序列化的几种方式(datacontractserializer)(二)</a>

<a target="_blank" href="http://blog.chinaunix.net/uid-20777859-id-546350.html">关于复杂类型的序列化 </a>