wcf是基于消息进行通信的,这篇就是简单说下序列化引擎是如何将.net object转化为xml消息。一般情况下很少用到这些,你只需定义数据协定之类的或者指定相应的序列化引擎,然后设置相应的特性就好。
序列化的方式有三种:DataContractSerializer、NetDataContractSerializer和XmlSerializer。前两种相似,简单说说说DataContractSerialier和XmlSerializer。
DataContractSerializer是默认序列化方式,要使用DataContractSerializer类,先要实例化一个该类
DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
Person是一个数据协定类。在我们定义数据协定的时候有个kownType,初始化DataContractSerializer类如下:
[DataContract] public class Person { } [DataContract] public class Man : Person { } [DataContract] public class Woman : Person { } Type[] kownTypes = new Type[]{typeof(Man),typeof(Woman)}; DataContractSerialzier dcs = new DataContractSerializer(typeof(Person),kownTypes);
至于默认根名称和命名空间就不多说了,说数据协定的时候就介绍过。最大对象配额(maxItemInObjectGraph),值为整数,指定序列化和反序列化的最大项数。如下对象数为3,即本身(Test)+Num+Str,当然,里面还可嵌套其他数据协定:
[DataContract] public class Test { [DataMember] public int Num {get;set;} [DataMember] public string Str {get;set;} }
往返行程是指对象反序列化和重新序列化时产生的从xml流到对象实例,再到xml流。往返行程的启用和禁止可通过ignoreExtensionDataObject参数的设置为true或者不实现IExtensibleDataObject接口(如果前面的文字描述让你对于往返行程没懂,那么你看到这个接口的时候,你应该也就明白它的用处了)。preserveObjectReferences参数(默认值为false),该参数的作用是设置对象图保留的,举个简单的例子
[DataContract] public class PurchaseOrder { [DataMember] public Address billTo; [DataMember] public Address shipTo; } [DataContract] public class Address { [DataMember] public string street; } Address adr = new Address(); adr.street = "123 Main St."; PurchaseOrder po = new PurchaseOrder{billTo=adr, shipTo=adr}; //perserveObjectReferences=true <PurchaseOrder ser:id="1"> <billTo ser:id="2"><street ser:id="3">123 Main st.</treet></billTo> <shipTo ser:ref="2" /> </PurchaseOrder> //perserveObjectReferences=false <PurchaseOrder> <billTo><street>123 Main st.</treet></billTo> <shipTo><street>123 Main st.</treet></shipTo> </PurchaseOrder>
如上,preserveObjectReferences=true时,如果一个对象被多次引用,不会被再在xml中创建该对象的节点,而是生成该对象的一个引用。注意的是当为true是,只有另一个preserveObjectReferences同样为true的DataContractSerializer才能理解;元数据不支持此功能;preserveObjectReferences=false时,需要复制对象,为true,虽不会复制对象,但是会进行额外的比较,导致序列化和反序列化进程减慢。
上面简单介绍了DataContractSerializer的构造,接下来说说序列化。
简单序列化:即使用基本的方法WriteObject,该方法使用指定的 System.IO.Stream 将对象的完整内容(开始、内容和结束)写入 XML 文档或流。
分布引导序列化:即使用WriteStartObject、WriteObjectContent和WriteEndObject分别写入结束元素,对象内容和关闭包装元素。该序列化方式有两种常见用法:一是在WriteStartObject和WriteObjectContent之间插入内容;二是完全避免使用WriteStartObject和WriteEndObject,并写入自定义的包装元素或者跳过写入包装。
反序列化最基本的方法就是调用ReadObject方法。
接下来说下XmlSerializer,XmlSerializer并非专用于WCF,它允许对生成的xml进行更多的控制并且支持更多的xml架构定义语言标准,说白点就是支持标准的xml,可以跨语言的传输。但不支持数据协定。要想将DataContractSerialzier切换到XmlSerialzier,只需在定义服务协定的时候声明XmlSerialzierFormat特性即可
[ServiceContract] [XmlSerializerFormat] public interface TestXmlSerialzier { [OperationContract] void SaveInfo(Person p); ...... } public class Person { [XmlAttribute] public string Name{get;set;} [XmlAttribute] public int Age{get;set;} }
DataContractSerializer序列化被DataContract和DataMember所标记的成员,而XmlSerialzier序列化所有的公共成员。
好了,终于迈过这个坎了!尼玛的。。。。。。