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.

      DataContractSerializer(Type type, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate)

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的更多相关文章

  1. ASP.NET MVC4中调用WEB API的四个方法

    http://tech.it168.com/a2012/0606/1357/000001357231_all.shtml [IT168技术]当今的软件开发中,设计软件的服务并将其通过网络对外发布,让各 ...

  2. ASP.NET MVC4 json序列化器

    ASP.NET MVC4中调用WEB API的四个方法 2012年06月07日00:05 it168网站原创 作者:廖煜嵘 编辑:景保玉 我要评论(0) [IT168技术]当今的软件开发中,设计软件的 ...

  3. mvc4项目数据库优先的尝试

    对于mvc代码优先原则,感觉真不知道为什么硬要设计这种模式,代码优先使得每次运行程序都要重建数据库,现实中这种模式有什么用呢. 数据库优先可能有好多方式,看了好久才做出来一种比较简单的.通过先添加一个 ...

  4. C#综合揭秘——分部类和分部方法

    在面向对象的“封装闭合性”开发原则中,一向提倡的是把独立的功能封装在一个类里面的!但从Visual Studio 2005开发,系统提供了一个分部类的开发方式一直受到争议,很多人认为把同一类的功能分布 ...

  5. 前端框架MVVM是什么(整理)

    前端框架MVVM是什么(整理) 一.总结 一句话总结:vm层(视图模型层)通过接口从后台m层(model层)请求数据,vm层继而和v(view层)实现数据的双向绑定. 1.我大前端应该不应该做复杂的数 ...

  6. 架构-MVVM:MVVM核心概念

    ylbtech-架构-MVVM:MVVM核心概念 1.返回顶部 1. MVVM模式是Model.View.ViewModel的简称,最早出现在WPF,现在Silverlight中也使用该模式,MVVM ...

  7. 找不到方法:“Boolean System.Runtime.Serialization.DataContractAttribute.get_IsReference()”的解决办法

    找不到方法:“Boolean System.Runtime.Serialization.DataContractAttribute.get_IsReference()”.的解决办法站点发布后部署到了两 ...

  8. WCF中DataContractAttribute 类

    一.这个类的作用 使用提供的数据协定,将类型实例序列化和反序列化为 XML 流或文档.无法继承此类,(DataContractSerializer 用于序列化和反序列化在 Windows Commun ...

  9. DataContractAttribute 类

    https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.datacontractattribute.aspx nam ...

随机推荐

  1. MySql将查询结果插入到另外一张表

    今天遇到一个业务需求是这样的:对在职员工超过55岁提醒.我想的思路是查询员工表,然后将超过55岁的人的信息存到另一个表,并且以消息的形式给用户提示,用户处理掉之后此消息失效(在数据库做标记). 不管是 ...

  2. msp430项目编程54

    msp430综合项目---扩展项目四54 1.电路工作原理 2.代码(显示部分) 3.代码(功能实现) 4.项目总结

  3. android调用邮件应用发送email

    直接贴代码: Intent intent = new Intent(android.content.Intent.ACTION_SEND); // 附件 File file = new File(En ...

  4. delphi使用IdHTTP模拟提交页面方法总结

    http://blog.csdn.net/lxdcyh/article/details/3986800 1.拖入TIdHTTP控件,HandleRedirect设为True,否则可能会出现HTTP 3 ...

  5. Chrome常用URL命令(伪URL)

    在Chrome地址栏输入chrome://chrome-urls/可以看到所有的Chrome支持的伪RUL 1.chrome://accessibility/ 可达性分析,默认是关闭的,点击acces ...

  6. 6.JAVA语言基础部分--数据库操作

    操作数据数据流程:得到Connecnt->获取Statement对象->执行sql语句返回ResultSet 1.通过DriverManager.getConnection("j ...

  7. vSphere 6.5 新功能 (7) - 支持 512e 硬盘

    2016-12-11 Newton 长期以来,机械硬盘在储存数据时,一直都是以 512 byte 大小的扇区(Sector)为单位分割进行读写.随着硬盘容量的不断提升,这种古老的分配标准已经越来越不合 ...

  8. 还在为不停build 烦恼么?看这里~~

    如果你是一名开发者,还在为偶尔改一个坐标或者颜色值 就要重新build 好久,然后如果层次深 还要一步步进去看效果么?下面 为大家介绍一个很好的开源库  DYCI  他的github地址,首先下载到本 ...

  9. 【Todo】UDP P2P打洞原理

    参考以下两篇文章: https://my.oschina.net/ososchina/blog/369206 http://m.blog.csdn.net/article/details?id=666 ...

  10. [Rust] Pass a JavaScript Function to WebAssembly and Invoke it from Rust

    In some cases it’s useful to be able to invoke a JavaScript function inside Rust. This session showc ...