数据契约的定义与数据契约序列化器(1)
5.2.2
同服务契约类似,WCF采用了基于特性(Attribute)的数据契约定义方式。基于数据契约的自定义特性主要包含以下两个:DataContractAttribute和DataMemberAttribute,接下来我们将讨论这两个重要的自定义特性。
DataContractAttribute和DataMemberAttribute
WCF通过应用DataContractAttribute特性将其目标类型定义成一个数据契约,下面是DataContractAttribute的定义。从AttributeUsage的定义来看,DataContractAttribute只能用于枚举、类和结构体,而不能用于接口;DataContractAttribute是不可以被继承的,也就是说当一个类型继承了一个应用了DataContractAttribute特性类型,自身也只有显式地应用DataContractAttribute特性才能成为数据契约;一个类型上只能应用唯一一个DataContractAttribute特性。
-
[AttributeUsage(AttributeTargets.Enum
|
AttributeTargets.Struct| -
InheritedAttributeTargets.Class, = false,
AllowMultiple = false)] -
public
sealed class DataContractAttribute : Attribute -
{
-
public bool IsReference { get; set; } -
public string Name { get; set; } -
public string Namespace { get; set; } -
}
DataContractAttribute仅仅包含3个属性成员。其中Name和Namespace表示数据契约的名称和命名空间;IsReference表示在进行序列化的时候是否保持对象现有的引用结构。比如说,一个对象的两个属性同时引用一个对象,那么有两种序列化方式,一种是在序列化后的XML仍然保留这种引用结构,另一种是将两个属性的值序列化成两份独立的具有相同内容的XML。
对于服务契约来说,我们将在一个接口或类上面应用的ServiceContractAttribute
-
[AttributeUsage(AttributeTargets.Field
| AttributeTargets.Property, -
Inherited= false,AllowMultiple = false)] -
public
sealed class DataMemberAttribute : Attribute -
{
-
public DataMemberAttribute(); -
-
public bool -
EmitDefaultValue
{ get; set; } -
public bool -
IsRequired
{ get; set; } -
public string -
Name
{ get; set; } -
public int -
Order
{ get; set; } -
}
下面的列表列出了DataMemberAttribute的4个属性所表述的含义。
Name:数据成员的名称,默认为字段或属性的名称。
Order:相应的数据成员在最终序列化的XML中出现的位置,Order值越小越靠前,默认值为 1。
IsRequired:表明属性成员是否是必须的成员,默认值为false,表明该成员是默认的。
EmitDefaultValue:表明在数据成员的值等于默认值的情况下,是否还须要将其序列化到最终的XML中,默认值为true,表示默认值会参与序列化。
注:
数据契约序列化器(DataContractSerializer)
在WCF中,数据契约的定义是为序列化和反序列化服务的。WCF采用数据契约序列化器(DataContractSerializer)作为默认的序列化器。在上面一节,介绍了XmlSerializer以及基于XmlSerializer的序列化规则,现在以相同的方式来介绍DataContractSerializer和基于DataContractSerializer采用的序列化规则。先来看看DataContractSerializer的定义。
-
public
sealed class DataContractSerializer :
XmlObjectSerializer -
{
-
//其他成员 -
public DataContractSerializer(Type type); -
//其他构造函数 -
-
public override object ReadObject(XmlReader reader); -
public override object ReadObject(XmlDictionaryReader
reader,bool -
verifyObjectName); -
public override object ReadObject(XmlReader reader, bool -
verifyObjectName); -
public override void WriteObject(XmlWriter writer,
objectgraph); -
-
public IDataContractSurrogate DataContractSurrogate { get; } -
public bool IgnoreExtensionDataObjec t { get; } -
<Type>public ReadOnlyCollection KnownTypes { get; } -
public int MaxItemsInObjectGraph { get; } -
public bool PreserveObjectReferences { get; } -
}
DataContractSerializer定义了一系列的重载的构造函数,我们可以调用它们构建相应的DataContractSerializer对象,通过制定相应的参数控制系列化器的序列化和反序列化行为。在后续的介绍中我们会通过这些相应的构造函数创建DataContractSerializer对象,在这里就不一一介绍了。DataContractSerializer主要通过两个方法进行序列化和反序列化:WriteObject和ReadObject。这里需要着重介绍一下DataContractSerializer的5个重要属性成员。
DataContractSurrogate:这是一个实现了IDataContractSurrogate接口的数据契约代理类的对象。契约代理会参与到DataContractSerializer的序列化、反序列化,以及契约的导入和导出的过程中,实现对象和类型的替换。
IgnoreExtensionDataObjec
KnownTypes:由于序列化和反序列化依赖于定义在类型的元数据信息,所以在进行序列化或反序列化之前,需要确定被序列化对象,或者反序列化生成对象的所有相关的真实类型。为了确保序列化或反序列化的成功,须要将相关的类型添加到KnownTypes类型集合中。
MaxItemsInObjectGraph:为了避免黑客生成较大数据,频繁地访问服务造成服务器不堪重负(我们一般把这种黑客行为称为拒绝服务DoS-Denial of Service),可以通过MaxItemsInObjectGraph属性设置进行序列化和反序列化允许的最大对象数。MaxItemsInObjectGraph的默认值为65536。
PreserveObjectReferences
