[爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道《天天山海经》为此录制的节目视频(苏州话)]]如果一个类型,不一定是数据契约,和给定的数据契约具有很大的差异,而我们要将该类型的对象序列化成基于数据契约对应的XML。反之,对于一段给定的基于数据契约的XML,要通过反序列化生成该类型的对象,我们该如何实现这样的场景?
比如下面定义了两个类型Contact和Customer,其中Customer是数据契约,Contact的Sex属性相当于Customer的Gender属性,而Contact的FullName可以看成是Customer的FirstName和LastName的组合。现在我们要做的是将一个Contact对象序列化成基于Customer数据契约对应的结构的XML,或者对于一段基于Customer数据契约对应结构的XML,将其反序列化生成Contact对象。
1: public class Contact<!--CRLF-->
2: { <!--CRLF-->
3: public string FullName<!--CRLF-->
4: { get; set; } <!--CRLF-->
5: <!--CRLF-->
6: public string Sex<!--CRLF-->
7: { get; set; } <!--CRLF-->
8: <!--CRLF-->
9: public override bool Equals(object obj)<!--CRLF-->
10: { <!--CRLF-->
11: Contact contact = obj as Contact;<!--CRLF-->
12: if (contact == null)<!--CRLF-->
13: { <!--CRLF-->
14: return false;<!--CRLF-->
15: } <!--CRLF-->
16: <!--CRLF-->
17: return this.FullName == contact.FullName && this.Sex == contact.Sex;<!--CRLF-->
18: } <!--CRLF-->
19: <!--CRLF-->
20: public override int GetHashCode()<!--CRLF-->
21: { <!--CRLF-->
22: return this.FullName.GetHashCode() ^ this.Sex.GetHashCode();<!--CRLF-->
23: } <!--CRLF-->
24: } <!--CRLF-->
1: [DataContract(Namespace = "http://www.artech.com")]<!--CRLF-->
2: public class Customer<!--CRLF-->
3: { <!--CRLF-->
4: [DataMember(Order = 1)] <!--CRLF-->
5: public string FirstName<!--CRLF-->
6: { get; set; } <!--CRLF-->
7: <!--CRLF-->
8: [DataMember(Order = 2)] <!--CRLF-->
9: public string LastName<!--CRLF-->
10: { get; set; } <!--CRLF-->
11: <!--CRLF-->
12: [DataMember(Order = 3)] <!--CRLF-->
13: public string Gender<!--CRLF-->
14: { get; set; } <!--CRLF-->
15: } <!--CRLF-->
为实现上面的要求,要涉及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<!--CRLF-->
2: { <!--CRLF-->
3: Type GetDataContractType(Type type); <!--CRLF-->
4: object GetObjectToSerialize(object obj, Type targetType);<!--CRLF-->
5: object GetDeserializedObject(object obj, Type targetType);<!--CRLF-->
6: <!--CRLF-->
7: object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType);<!--CRLF-->
8: object GetCustomDataToExport(Type clrType, Type dataContractType);<!--CRLF-->
9: void GetKnownCustomDataTypes(Collection<Type> customDataTypes);<!--CRLF-->
10: Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData);<!--CRLF-->
11: CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit); <!--CRLF-->
12: } <!--CRLF-->
现在我专门为Contact和Customer之间的转换创建了一个自定义的DataContractSurrogate:ContractSurrogate。在GetDataContractType中,如果发现类型是Contact,则替换成Customer。在GetObjectToSerialize方法中,将用于序列化的Contact对象用Customer对象替换,而在GetDeserializedObject中则用Contact对象替换反序列化生成的Customer对象。
1: public class ContractSurrogate : IDataContractSurrogate<!--CRLF-->
2: { <!--CRLF-->
3: <!--CRLF-->
4: public object GetCustomDataToExport(Type clrType, Type dataContractType)<!--CRLF-->
5: { <!--CRLF-->
6: return null;<!--CRLF-->
7: } <!--CRLF-->
8: <!--CRLF-->
9: public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)<!--CRLF-->
10: { <!--CRLF-->
11: return null;<!--CRLF-->
12: } <!--CRLF-->
13: <!--CRLF-->
14: public Type GetDataContractType(Type type)<!--CRLF-->
15: { <!--CRLF-->
16: if (type == typeof(Contact))<!--CRLF-->
17: { <!--CRLF-->
18: return typeof(Customer);<!--CRLF-->
19: } <!--CRLF-->
20: <!--CRLF-->
21: return type;<!--CRLF-->
22: } <!--CRLF-->
23: <!--CRLF-->
24: public object GetDeserializedObject(object obj, Type targetType)<!--CRLF-->
25: { <!--CRLF-->
26: Customer customer = obj as Customer;<!--CRLF-->
27: if (customer == null)<!--CRLF-->
28: { <!--CRLF-->
29: return obj;<!--CRLF-->
30: } <!--CRLF-->
31: <!--CRLF-->
32: return new Contact<!--CRLF-->
33: { <!--CRLF-->
34: FullName = string.Format("{0} {1}", customer.FirstName, customer.LastName),<!--CRLF-->
35: Sex = customer.Gender <!--CRLF-->
36: }; <!--CRLF-->
37: } <!--CRLF-->
38: <!--CRLF-->
39: public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)<!--CRLF-->
40: { <!--CRLF-->
41: <!--CRLF-->
42: } <!--CRLF-->
43: <!--CRLF-->
44: public object GetObjectToSerialize(object obj, Type targetType)<!--CRLF-->
45: { <!--CRLF-->
46: Contact contact = obj as Contact;<!--CRLF-->
47: if (contact == null)<!--CRLF-->
48: { <!--CRLF-->
49: return obj;<!--CRLF-->
50: } <!--CRLF-->
51: <!--CRLF-->
52: <!--CRLF-->
53: return new Customer<!--CRLF-->
54: { <!--CRLF-->
55: FirstName = contact.FullName.Split(" ".ToCharArray())[0],<!--CRLF-->
56: LastName = contact.FullName.Split(" ".ToCharArray())[1],<!--CRLF-->
57: Gender = contact.Sex <!--CRLF-->
58: }; <!--CRLF-->
59: } <!--CRLF-->
60: <!--CRLF-->
61: public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)<!--CRLF-->
数据契约代理实践
901

被折叠的 条评论
为什么被折叠?



