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. 

      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); 

 

转载于:https://www.cnblogs.com/chucklu/p/9988472.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将C#的实体类转换为SOAP报文,可以使用.NET框架提供的System.Runtime.Serialization命名空间中的DataContractSerializer类。以下是一个简单的示例代码: ```csharp using System; using System.IO; using System.Runtime.Serialization; using System.Xml; using System.Xml.Serialization; namespace ConsoleApp1 { [DataContract] public class Person { [DataMember] public string Name { get; set; } [DataMember] public int Age { get; set; } [DataMember] public string Address { get; set; } } class Program { static void Main(string[] args) { // 创建一个Person对象 Person person = new Person(); person.Name = "张三"; person.Age = 20; person.Address = "北京市"; // 创建DataContractSerializer对象 DataContractSerializer serializer = new DataContractSerializer(typeof(Person)); // 创建一个MemoryStream对象,用于保存序列化后的SOAP报文 MemoryStream stream = new MemoryStream(); // 将Person对象序列化为SOAP报文,并保存到MemoryStream对象中 serializer.WriteObject(stream, person); // 将MemoryStream对象转换为字符串,即为SOAP报文 string soapMessage = Encoding.UTF8.GetString(stream.ToArray()); // 输出SOAP报文 Console.WriteLine(soapMessage); Console.ReadLine(); } } } ``` 在上面的示例代码中,我们创建了一个名为Person的实体类,并使用DataContractAttribute标记需要序列化的属性。然后创建了一个DataContractSerializer对象,并将Person对象序列化为SOAP报文,并将其保存到MemoryStream对象中。最后将MemoryStream对象转换为字符串,即为SOAP报文。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值