Another new WCF feature that’s part of .NET 3.5 SP1 has to do with better support for object references. DataContractSerializer has always supported serializing object references and dealing with graphs, including cycles, and not just simple trees. But doing so is not the default behavior — you have to tell DataContractSerializer that you want it to preserve object references when you instantiate it.
Let’s look at a simple example. Supposed that you have the following cyclic object graph (I’m assuming the same Person type that I used in my previous post):
Person p = new Person();
p.Id = “123”;
p.Name = “Aaron”;
p.Spouse = new Person();
p.Spouse.Id = “456”;
p.Spouse.Name = “Monica”;
p.Spouse.Spouse = p;
…
And now let’s supposed that you want to serialize it. If you create the DataContractSerializer using the default constructor, it will throw an exception when it identifies the cycle during serialization. However, you can tell DataContractSerializer to preserve object references using one of the other constructors:
DataContractSerializer dcs = new DataContractSerializer(typeof(Person),
null, int.MaxValue, false, true /* preserve object refs */, null);
using (FileStream fs = new FileStream(“person.xml”, FileMode.Create))
{
dcs.WriteObject(fs, p);
}
The resulting person.xml file now looks like this:
<Person z:Id=“1“ xmlns=“http://schemas.datacontract.org/2004/07/SerializationSp1“ xmlns:i=“http://www.w3.org/2001/XMLSchema-instance“ xmlns:z=“http://schemas.microsoft.com/2003/10/Serialization/“>
<Id z:Id=“2“>123</Id>
<Name z:Id=“3“>Aaron</Name>
<Spouse z:Id=“4“>
<Id z:Id=“5“>456</Id>
<Name z:Id=“6“>Monica</Name>
<Spouse z:Ref=“1“ i:nil=“true“/>
</Spouse>
</Person>
Notice that each reference type has been given an “Id” attribute and the nested Spouse reference refers back to the containing Person via the Ref attribute, thereby preserving the references within the XML.
Now, as of SP1, the definitions for the Id/Ref attributes are now part of the generated schema. If you run SvcUtil.exe /dconly over the assembly containing Person, it will produce a schema file for the “http://schemas.microsoft.com/2003/10/Serialization” namespace. And within that schema, you’ll find the following definitions for Id/Ref, which are defined as ID/IDREF types:
…
<xs:attribute name=“Id“ type=“xs:ID“ />
<xs:attribute name=“Ref“ type=“xs:IDREF“ />
…
ID and IDREF are standard DTD/XSD types that are widely supported across platforms.
One problem with employing this object-reference-preservation technique is that you don’t have direct control over how the DataContractSerializer is constructed when defining your WCF services. You can, however, implement a behavior that intercepts the standard serializer creation process so that you can enable this feature. Sowmy provides a complete example of how to accomplish this over on his blog.