Welcome

首页 / 软件开发 / WCF / WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用

WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用2012-11-03 cnblogs Artech如果一个类型,不一定是数据契约,和给定的数据契约具有很大的差异,而我们要将该类型的对象序列化成基于数据契约对应的XML。反之,对于一段给定的基于数据契约的XML,要通过反序列化生成该类型的对象,我们该如何实现这样的场景?

比如下面定义了两个类型Contact和Customer,其中Customer是数据契约,Contact的Sex属性相当于Customer的Gender属性,而Contact的FullName可以看成是Customer的FirstName和LastName的组合。现在我们要做的是将一个Contact对象序列化成基于Customer数据契约对应的结构的XML,或者对于一段基于Customer数据契约对应结构的XML,将其反序列化生成Contact对象。

 1: public class Contact
2: {
3: public string FullName
4: { get; set; }
5:
6: public string Sex
7: { get; set; }
8:
9: public override bool Equals(object obj)
10: {
11: Contact contact = obj as Contact;
12: if (contact == null)
13: {
14: return false;
15: }
16:
17: return this.FullName == contact.FullName && this.Sex == contact.Sex;
18: }
19:
20: public override int GetHashCode()
21: {
22: return this.FullName.GetHashCode() ^ this.Sex.GetHashCode();
23: }
24: }
1: [DataContract(Namespace = "http://www.artech.com")]
2: public class Customer
3: {
4: [DataMember(Order = 1)]
5: public string FirstName
6: { get; set; }
7:
8: [DataMember(Order = 2)]
9: public string LastName
10: { get; set; }
11:
12: [DataMember(Order = 3)]
13: public string Gender
14: { get; set; }
15: }
为实现上面的要求,要涉及WCF中一个特殊的概念:数据契约代理(DataContract Surrogate)。WCF通过一个接口System.Runtime.Serialization.IDataContractSurrogate来表示数据契约代理。IDataContractSurrogate用于实现在序列化、反序列化、数据契约的导入和导出过程中对对象或者类型的替换。以上面Contact和Customer为例,在正常的情况下,DataContractSerializer针对类型Customer对一个真正的Customer对象进行序列化,现在要求的是通过DataContractSerializer序列化一个Contact对象,并且要生成与Customer等效的XML,就要在序列化的过程中实现类型的替换(由Contact类型替换成Customer类型)和对象的替换(由Contact对象替换成Customer对象)。

我们先来看看IDataContractSurrogate的定义,序列化相关的方法有以下3个,如果想具体了解IDataContractSurrogate在数据契约导入、导出,以及代码生成方面的应用可以参考MSDN相关文档,在这里就不多作介绍了。

GetDataContractType:获取进行序列化、反序列化或者数据契约导入导出基于的数据契约的类型,实现此方法相当于实现了类型的替换;

GetObjectToSerialize:在序列化之前获取序列化的对象,实现了此方法相当于为序列化实现了对象替换;

GetDeserializedObject:当完成反序列化工作后,通过方法获得被反序列化生成的对象,通过此方法可以用新的对象替换掉真正被反序列化生成的原对象。

 1: public interface IDataContractSurrogate
2: {
3: Type GetDataContractType(Type type);
4: object GetObjectToSerialize(object obj, Type targetType);
5: object GetDeserializedObject(object obj, Type targetType);
6:
7: object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType);
8: object GetCustomDataToExport(Type clrType, Type dataContractType);
9: void GetKnownCustomDataTypes(Collection<Type> customDataTypes);
10: Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData);
11: CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit);
12: }