2009-04-26 6 views
4

Je suis en train d'écrire une application WCF qui sera consommée par une application Silverlight. J'ai fait la plupart du travail de conception et je suis en train de faire la mise en œuvre, ce qui m'a amené à poser cette question.DataContractSerializer sérialisation du même objet plus d'une fois par requête

Voici un exemple de quelque chose qui existe dans ma demande:

[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 

    ... 
} 

Voici ce que je veux en venir: Dans ma demande mostRecentlyUsedTowel pointera quelque chose dans la liste des serviettes pour la salle de sport de la personne . Certaines de mes demandes sérialiseront un objet Personne.

Le DataContractSerializer est-il assez intelligent pour remarquer qu'il lui est demandé de sérialiser deux fois exactement la même instance d'un objet? Si oui, comment y réagit-il?

Si l'on va juste faire deux fois la sérialisation de la même instance, comment dois-je gérer cela pour ne pas envoyer de données inutiles sur le lien?

Répondre

7

Le code suivant:

[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; } 
} 

évaluera à:

<?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> 

Si vous avez ajouté la propriété IsReference à l'attribut DataContract de la classe serviette comme ceci:

[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; } 
} 

vous obtiendrez une sortie comme celle-ci:

<?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> 

Espérons que ça aide.

+0

C'est exactement ce que je cherchais. Merci beaucoup. – Craig

Questions connexes