博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WCF 第六章 序列化与编码 保留引用和循环引用
阅读量:5911 次
发布时间:2019-06-19

本文共 5731 字,大约阅读时间需要 19 分钟。

关于引用和序列化有两个重要的问题。这两个问题都是关于通过引用保留跟踪的。当你试着优化需要序列化的数据总量或者当在客户端和服务端共享类型信息时保留引用将会起很重要的作用。

  引用保留允许同样的数据在一个数据契约中引用多于一次而不用重复数据。当你使用数据可能被引用多于一次的列表,数组和哈希表等数据结构时,保留引用这是一 个很常用的场景。通过保留引用,数据在它第一次出现在数据契约中时被序列化然这个数据的所有顺序出现都以引用的形式。这可以在序列化时并且数据被引用多次 的时候实现减少数据总量的预期重要效果。

  循环引用是指一个对象维持对子对象的引用,子对象还会对其引用。关于循环引用的一个例子是一个子对象维持到父对象的父子关系。这些情况的类型在面向对象编 程中很常用。对象维护循环引用的问题是序列化不可能没有对引用保留的支持。任何序列化结构将会在一个试着序列化对象的无终止循环中终止。引用保留允许对使 用的数据添加一个引用而不是对数据反复序列化。

  DataContractSerializer 默认不允许保留引用。引用保留对NetDataContractSerializer和XmlSerializer默认开启。如果你打算在客户端和服务端 之间共享类型信息你可以使用这些序列化方法中的一个。否则,你还可以在DataContractSerializer上使用一个自定义属性来支持引用保 留。

提示 使用IXmlSerializable 来支持引用保留

支持引用保留需要使用代码来实现如果你计划使用IXmlSerializable来使用自定义序列化

  让我们看一下列表6.14中的一个例子。首先,一个列表从List<Employee>中创建。然后几个Employee对象被添加到列表中。

列表6.14保留引用的需要

01 [ServiceContract]
02     public interface IEmployeeInformation
03     {
04         [OperationContract]
05         Employee[] GetEmployeesOfTheMonth();
06     }
07     public class EmployeeInformation : IEmployeeInformation
08     {
09         public EmployeeInformation()
10         {
11         }
12  
13         public Employee[] GetEmployeesOfTheMonth()
14         {
15             List<Employee> list = new List<Employee>(6);
16             Employee employee1 = new Employee(1, "John", "Doe");
17             Employee employee2 = new Employee(2, "Jane", "Doe");
18             Employee employee3 = new Employee(3, "John", "Smith");
19  
20             list.Add(employee1);
21             list.Add(employee2);
22             list.Add(employee3);
23             list.Add(employee1);
24             list.Add(employee2);
25             list.Add(employee3);
26  
27             return list.ToArray();
28         }
29     }

  默认情况下,DataContractSerializer将会将数据的每一个引用都作为一个单独的拷贝序列化。列表6.15的输出显示了Employee1, Employee2,Employee3出现了多次。

列表6.15 没有保留引用的序列化列表

01 <ArrayOfEmployee xmlns="" xmlns:i="">
02 - <Employee>
03   <EmployeeID>1</EmployeeID>
04   <FirstName>John</FirstName>
05   <LastName>Doe</LastName>
06   </Employee>
07 - <Employee>
08   <EmployeeID>2</EmployeeID>
09   <FirstName>Jane</FirstName>
10   <LastName>Doe</LastName>
11   </Employee>
12 - <Employee>
13   <EmployeeID>3</EmployeeID>
14   <FirstName>John</FirstName>
15   <LastName>Smith</LastName>
16   </Employee>
17 - <Employee>
18   <EmployeeID>1</EmployeeID>
19   <FirstName>John</FirstName>
20   <LastName>Doe</LastName>
21   </Employee>
22 - <Employee>
23   <EmployeeID>2</EmployeeID>
24   <FirstName>Jane</FirstName>
25   <LastName>Doe</LastName>
26   </Employee>
27 - <Employee>
28   <EmployeeID>3</EmployeeID>
29   <FirstName>John</FirstName>
30   <LastName>Smith</LastName>
31   </Employee>
32   </ArrayOfEmployee>

  为了保留引用,通过向DataContractSerializer构造函数的preserveObjectReference参数传递一个true值来 应用一个自定义行为并创建一个实例。行为是WCF中的扩展结构,允许你修改运行时的默认行为;它将会在第五章"行为"中介绍。在这种情况下它允许我们通过 修改DataContractSerializer默认行为来支持引用保留。列表6.16完成一个自定义行为来描述这个。

列表6.16 使用一个自定义行为来完成引用保留

01 using System.ServiceModel.Description;
02 using System.Runtime.Serialization;
03 using System.ServiceModel.Dispatcher;
04 using System.ServiceModel.Channels;
05  
06 namespace SerializerUtility
07 {
08     public class ReferencePreservingDataContractFormatAttribute : Attribute, IOperationBehavior
09     {
10         #region IOperationBehavior 成员
11  
12         public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
13         {
14         }
15  
16         public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
17         {
18             IOperationBehavior innerBehavior = new ReferencePreservingDataContractSerializerOperationBehavior(operationDescription);
19             innerBehavior.ApplyClientBehavior(operationDescription, clientOperation);
20         }
21  
22         public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
23         {
24             IOperationBehavior innerBehavior = new ReferencePreservingDataContractSerializerOperationBehavior(operationDescription);
25             innerBehavior.ApplyDispatchBehavior(operationDescription, dispatchOperation);
26         }
27  
28         public void Validate(OperationDescription operationDescription)
29         {
30         }
31  
32         #endregion
33     }
34  
35     public class ReferencePreservingDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
36     {
37         private static XmlObjectSerializer CreateDataContractSerializer(Type type, string name,
38             string ns, IList<Type> knownTyps)
39         {
40             return CreateDataContractSerializer(type, name, ns, knownTyps);
41         }
42  
43         public ReferencePreservingDataContractSerializerOperationBehavior(OperationDescription operationDescription) : base(operationDescription)
44         {
45         }
46  
47         public override System.Runtime.Serialization.XmlObjectSerializer CreateSerializer(Type type,
48             string name, string ns, IList<Type> knownTypes)
49         {
50             return CreateDataContractSerializer(type, name, ns, knownTypes);
51         }
52  
53         public override System.Runtime.Serialization.XmlObjectSerializer CreateSerializer(Type type,
54             System.Xml.XmlDictionaryString name, System.Xml.XmlDictionaryString ns, IList<Type> knownTypes)
55         {
56             return new DataContractSerializer(type, name, ns, knownTypes, 0x7fff, false, true, null);
57         }
58     }
59 }

 对我们的操作契约应用这个属性的结果在列表6.17中显示。输出结果显示Employee1, Employee2和Employee3仅出现一次,但是它们现在使用一个属性标记,z:Id, 当做一个引用标记符使用。其他的对这些对象的引用标识符使用z:Ref属性表示。

列表6.17 使用引用保留的序列化列表

01 - <ArrayOfEmployee xmlns="" xmlns:i="">
02 - <Employee z:Id="i1" xmlns:z="">
03   <EmployeeID>1</EmployeeID>
04   <FirstName>John</FirstName>
05   <LastName>Doe</LastName>
06   </Employee>
07 - <Employee z:Id="i2" xmlns:z="">
08   <EmployeeID>2</EmployeeID>
09   <FirstName>Jane</FirstName>
10   <LastName>Doe</LastName>
11   </Employee>
12 - <Employee z:Id="i3" xmlns:z="">
13   <EmployeeID>3</EmployeeID>
14   <FirstName>John</FirstName>
15   <LastName>Smith</LastName>
16   </Employee>
17   <Employee z:Ref="i1" xmlns:z="" />
18   <Employee z:Ref="i2" xmlns:z="" />
19   <Employee z:Ref="i3" xmlns:z="" />
20   </ArrayOfEmployee>

=======
转载自
作者:DanielWise
出处:http://www.cnblogs.com/danielWise/
 

转载于:https://www.cnblogs.com/llbofchina/archive/2011/06/30/2094152.html

你可能感兴趣的文章
洛谷P2805 植物大战僵尸
查看>>
后缀数组专题
查看>>
一次因为文件名开头包含空格而导致FTP文件一直无法下载的悲剧!
查看>>
linux测试某进程占用oi、cpu、内存的使用情况
查看>>
jQery简单Tab选项卡效果
查看>>
Java Object类及其equals方法
查看>>
ICMP控制报文协议
查看>>
[摘录]为你的感情开个账户
查看>>
redhat下配置SEED DVS6446开发环境2
查看>>
团队博客作业Week4 --- 学霸网站--NABC
查看>>
python 安装 setuptools Compression requires the (missing) zlib module 的解决方案
查看>>
Nginx的配置使用
查看>>
pytorch1.0 tutorial note
查看>>
2.C#中泛型在方法Method上的实现
查看>>
Jenkins控制台显示乱码
查看>>
渗透测试之无文件渗透简单使用-windows
查看>>
FindBugs规则整理
查看>>
Mysql MERGE 引擎在分表环境下得使用
查看>>
蓝牙 bluez 的编程 C C++
查看>>
建立一个全数据管理的分析平台,该如何落实?
查看>>