DataContractAttribute.IsReference
IsReference property in data contract
It determines how objects are serialized, by default, IsReference=false.
Setting IsReference = true allows the serialization of trees of objects that can reference each other. So with a list of Employees that each have a property for Manager (who is also an Employee), a reference to the Manager for each Employee can be held rather than embedding the Manager within each Employee node:
IsReference=false would produce:
<Employee>
<Manager i:nil=“true“ />
<Name>Kenny</Name>
</Employee>
<Employee>
<Manager>
<Manager i:nil=“true“ />
<Name>Kenny</Name>
</Manager>
<Name>Bob</Name>
</Employee>
<Employee>
<Manager>
<Manager i:nil=“true“ />
<Name>Kenny</Name>
</Manager>
<Name>Alice</Name>
</Employee>
Where as IsReference=true would produce:
<Employee z:Id=“i1“ xmlns:z=“http://schemas.microsoft.com/2003/10/Serialization/“>
<Manager i:nil=“true“ />
<Name>Kenny</Name>
</Employee>
<Employee z:Id=“i2“ xmlns:z=“http://schemas.microsoft.com/2003/10/Serialization/“>
<Manager z:Ref=“i1“ />
<Name>Bob</Name>
</Employee>
<Employee z:Id=“i3“ xmlns:z=“http://schemas.microsoft.com/2003/10/Serialization/“>
<Manager z:Ref=“i1“ />
<Name>Alice</Name>
</Employee>
Snippets taken from this weblog that has a full explanation along with examples of the generated XML with the property applied.
MSDN - IsReference Property provides details as well as Interoperable Object References.
DataContract Serializer and IsReference property
In .net Framework 3.5 SP1, DataContractSerializer supports by-ref object graph serialization by using the standard xsd:ID/xsd:IDREF attributes.
You can set the IsReference=true on your DataContract definition and serializer will generate XML elements with IDs/IDREFs attributes and will link them together rather embedding them inside each other(default behavior).
Also if you examine the XSD generated by WCF as part of the metadata export, it will also contain the standard ID/IDREF xml schema attributes. Because of this, xml can be correctly parsed and understood by any framework in a standard way.
This change will enable serialization of object graphs having circular references (which wasn’t possible previously – at least not without writing custom code) and will also reduce the size of the serialized xml.
Let’s examine this change using the following DataContract definition:
[DataContract]
public class Employee
{
[DataMember]
public string Name { get; set; }
[DataMember]
public Employee Manager { get; set; }
}
[DataContract]
public class Department
{
[DataMember]
public List<Employee> Staff { get; set; }
[DataMember]
public string DeptName { get; set; }
}
Now if we serialize following Department object using DataContractSerializer
var kenny = new Employee() { Name = "Kenny" };
var bob = new Employee() { Name = "Bob", Manager = kenny };
var alice = new Employee() { Name = "Alice", Manager = kenny };
var ahmed = new Employee() { Name = "Ahmed", Manager = kenny };
var dept = new Department() { DeptName = "RandD", Staff = new List<Employee>() { kenny, bob, alice, ahmed } };
DataContractSerializer dcs = new DataContractSerializer(typeof(Department));
var ms = new MemoryStream();
dcs.WriteObject(ms, dept);
ms.Seek(0, SeekOrigin.Begin);
var sr = new StreamReader(ms);
var xml = sr.ReadToEnd();
We will get this xml.
<Department xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication2" xmlns:i="http://www.w3.org/2001/XMLSchemainstance">
<DeptName>RandD</DeptName>
<Staff>
<Employee>
<Manager i:nil="true" />
<Name>Kenny</Name>
</Employee>
<Employee>
<Manager>
<Manager i:nil="true" />
<Name>Kenny</Name>
</Manager>
<Name>Bob</Name>
</Employee>
<Employee>
<Manager>
<Manager i:nil="true" />
<Name>Kenny</Name>
</Manager>
<Name>Alice</Name>
</Employee>
<Employee>
<Manager>
<Manager i:nil="true" />
<Name>Kenny</Name>
</Manager>
<Name>Ahmed</Name>
</Employee>
</Staff>
</Department>
You can see manager Kenny is included in all Employee objects, essentially a by-value inclusion. Now if we change the declaration of Employee class to following:
[DataContract(IsReference = true)]
public class Employee
{
[DataMember]
public string Name { get; set; }
[DataMember]
public Employee Manager { get; set; }
}
With above change, you will get following different xml.
<Department xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication2" xmlns:i="http://www.w3.org/2001/XMLSchemainstance">
<DeptName>R&D</DeptName>
<Staff>
<Employee z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<Manager i:nil="true" />
<Name>Kenny</Name>
</Employee>
<Employee z:Id="i2" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<Manager z:Ref="i1" />
<Name>Bob</Name>
</Employee>
<Employee z:Id="i3" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<Manager z:Ref="i1" />
<Name>Alice</Name>
</Employee>
<Employee z:Id="i4" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<Manager z:Ref="i1" />
<Name>Ahmed</Name>
</Employee>
</Staff>
</Department>
In attribute-free (POCO) world:
you can use a different ctor, taking a boolean flag, to toggle by-val/by-ref serialization.
To enable circular references for operation or service scope, you can use custom behaviors etc. Essentially you need the ability to hook into serializer instantiation process and create the instance using above overload:
1. Subclass DataContractSerializerOperationBehavior
2. Ovverride CreateSerializer method
3. Create a new DCS instance passing true to preserveObjectReferences param.
class DataContractSerializerOperationBehaviorEx : DataContractSerializerOperationBehavior
{
public DataContractSerializerOperationBehaviorEx(OperationDescription operation):base(operation)
{
}
public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes, this.MaxItemsInObjectGraph, this.IgnoreExtensionDataObject, true, this.DataContractSurrogate);
}
public override XmlObjectSerializer CreateSerializer(Type type, System.Xml.XmlDictionaryString name, System.Xml.XmlDictionaryString ns, IList<Type> knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes, this.MaxItemsInObjectGraph, this.IgnoreExtensionDataObject, true, this.DataContractSurrogate);
}
}
DataContractAttribute.IsReference的更多相关文章
- ASP.NET MVC4中调用WEB API的四个方法
http://tech.it168.com/a2012/0606/1357/000001357231_all.shtml [IT168技术]当今的软件开发中,设计软件的服务并将其通过网络对外发布,让各 ...
- ASP.NET MVC4 json序列化器
ASP.NET MVC4中调用WEB API的四个方法 2012年06月07日00:05 it168网站原创 作者:廖煜嵘 编辑:景保玉 我要评论(0) [IT168技术]当今的软件开发中,设计软件的 ...
- mvc4项目数据库优先的尝试
对于mvc代码优先原则,感觉真不知道为什么硬要设计这种模式,代码优先使得每次运行程序都要重建数据库,现实中这种模式有什么用呢. 数据库优先可能有好多方式,看了好久才做出来一种比较简单的.通过先添加一个 ...
- C#综合揭秘——分部类和分部方法
在面向对象的“封装闭合性”开发原则中,一向提倡的是把独立的功能封装在一个类里面的!但从Visual Studio 2005开发,系统提供了一个分部类的开发方式一直受到争议,很多人认为把同一类的功能分布 ...
- 前端框架MVVM是什么(整理)
前端框架MVVM是什么(整理) 一.总结 一句话总结:vm层(视图模型层)通过接口从后台m层(model层)请求数据,vm层继而和v(view层)实现数据的双向绑定. 1.我大前端应该不应该做复杂的数 ...
- 架构-MVVM:MVVM核心概念
ylbtech-架构-MVVM:MVVM核心概念 1.返回顶部 1. MVVM模式是Model.View.ViewModel的简称,最早出现在WPF,现在Silverlight中也使用该模式,MVVM ...
- 找不到方法:“Boolean System.Runtime.Serialization.DataContractAttribute.get_IsReference()”的解决办法
找不到方法:“Boolean System.Runtime.Serialization.DataContractAttribute.get_IsReference()”.的解决办法站点发布后部署到了两 ...
- WCF中DataContractAttribute 类
一.这个类的作用 使用提供的数据协定,将类型实例序列化和反序列化为 XML 流或文档.无法继承此类,(DataContractSerializer 用于序列化和反序列化在 Windows Commun ...
- DataContractAttribute 类
https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.datacontractattribute.aspx nam ...
随机推荐
- Linux(15):shell 编程
shell基础 什么是 shell ? Shell是一个命令解释器,它的作用是解释执行用户输入的命令及程序等,用户输入一条命令, Shell 就解释执行一条. 这种从键盘一输入命令,就可以立即得到回应 ...
- Subsequence(hdu 3530)
题意:给你一个长度为n的数列,要求一个子区间,使得区间的最大值与最小值的差s满足,m<=s<=k,求满足条件的最长子区间 /* 单调队列 我们可以用单调队列分别维护最大值和最小值 当差值大 ...
- [Hihocoder 1289] 403 Forbidden (微软2016校园招聘4月在线笔试)
传送门 #1289 : 403 Forbidden 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Little Hi runs a web server. Someti ...
- Linux下AT&T汇编语法格式与Intel汇编语法格式异同
由于绝大多数的国内程序员以前只接触过Intel格式的汇编语言,很少或几乎没有接触过AT&T汇编语言,虽然这些汇编代码都是Intel风格的.但在Unix和Linux系统中,更多采用的还是AT&a ...
- 【Android】状态栏通知Notification、NotificationManager详解(转)
在Android系统中,发一个状态栏通知还是很方便的.下面我们就来看一下,怎么发送状态栏通知,状态栏通知又有哪些参数可以设置? 首先,发送一个状态栏通知必须用到两个类: NotificationMa ...
- 洛谷P2058 仪仗队
P2058 仪仗队 24通过 34提交 题目提供者shengmingkexue 标签数论(数学相关) 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 暂时没有讨论 题目描述 作为体育委员,C君 ...
- MAPZONE GIS SDK接入Openlayers3之五——图形编辑工具
图形编辑工具提供对要素图形进行增.删.改的功能,具体包括以下几种工具类型: 浏览工具 选择工具 创建要素工具 删除命令 分割工具 合并命令 节点编辑工具 修边工具 撤销命令 重做命令 工具的实现基本上 ...
- Go -- log4go日志
折腾: [已解决]go语言中实现log信息同时输出到文件和控制台(命令行) 期间,已经通过io的MultiWriter搞定了同时输出信息到文件和console,但是不支持level. 所以,再去试试这 ...
- 如何在List集合中去重
众所周知List集合中的元素是有序的,但是List中的元素同样是可以重复的,那么我们应该怎么在List集合中去重呢? 方法一: 对于方法一而言,这也许是一个小窍门.利用的是Set集合中不允许出现重复的 ...
- requirejs中的define
关于requirejs中的define的原理理解 我们已经了解到模块模式是为单例创建私有变量和特权方法的.一个最基本的例子: var foo=(function(){ var something= ...