DataContractSerializer serializes the same object more than once per request

I am writing a WCF application that will be used by the Silverlight application. I have done most of the design work, and now I am completing this task, which made me come up with this question.

Here is an example of what exists in my application:

[DataContract] class Person { [DataMember] private Towel mostRecentlyUsedTowel; [DataMember] private Gym gym; //the gym that this person attends ... } 
 [DataContract] class Gym { [DataMember] private List<Towel> towels; //all the towels this gym owns ... } 

Here's what I get: In my application, mostRecentlyUsedTowel will point to something in the gym towel list. Some of my queries will serialize the Person object.

Is the DataContractSerializer smart enough to notice that it has been asked to serialize the same instance of the object twice? If so, how does he deal with this?

If it just starts serializing the same instance twice, how can I do this so that I don't send unnecessary data by reference?

+4
source share
1 answer

The following code:

 [TestMethod] public void CanSerializePerson() { var towel1 = new Towel() { Id = 1 }; var towel2 = new Towel() { Id = 2 }; var towel3 = new Towel() { Id = 3 }; var gym = new Gym(); gym.towels.Add(towel1); gym.towels.Add(towel2); gym.towels.Add(towel3); var person = new Person() { recentlyUsedTowel = towel1, gym = gym }; var sb = new StringBuilder(); using (var writer = XmlWriter.Create(sb)) { var ser = new DataContractSerializer(typeof (Person)); ser.WriteObject(writer, person); } throw new Exception(sb.ToString()); } public class Person { public Towel recentlyUsedTowel { get; set; } public Gym gym { get; set; } } public class Gym { public Gym() { towels = new List<Towel>(); } public List<Towel> towels { get; set; } } public class Towel { public int Id { get; set; } } 

will evaluate:

 <?xml version="1.0" encoding="utf-16"?> <Person xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org"> <gym> <towels> <Towel><Id>1</Id></Towel> <Towel><Id>2</Id></Towel> <Towel><Id>3</Id></Towel> </towels> </gym> <recentlyUsedTowel><Id>1</Id></recentlyUsedTowel> </Person> 

If you added the IsReference property to the DataContract attribute of the Towel class as follows:

 [DataContract(IsReference=true)] public class Towel { // you have to specify a [DataMember] in this because you are // explicitly adding DataContract [DataMember] public int Id { get; set; } } 

you get the following output:

 <?xml version="1.0" encoding="utf-16"?> <Person xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org"> <gym> <towels> <Towel z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"> <Id>1</Id> </Towel> <Towel z:Id="i2" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"> <Id>2</Id> </Towel> <Towel z:Id="i3" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"> <Id>3</Id> </Towel> </towels> </gym> <recentlyUsedTowel z:Ref="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" /> </Person> 

Hope this helps.

+7
source

All Articles