Le message d'exception Deserialized object with reference id 'i53' not found in stream
peut s'afficher lorsque vous activez la fonctionnalité object reference preservation du sérialiseur de contrat de données. Il indique que, lors de la désérialisation, une référence à un objet indéfini a été rencontrée, et ne peut donc pas être désérialisée.
J'ai été capable de reproduire le problème en obsolérant un membre de données comme suit. Tout d'abord, je définissais les types suivants:
namespace V1
{
[DataContract(Name = "Member", Namespace = "Question45008433", IsReference = true)]
public class Member
{
[DataMember]
public string Name { get; set; }
}
[DataContract(Name = "Root", Namespace = "Question45008433")]
public class RootObject
{
[DataMember(Order = 1)]
public Member MainMember { get; set; }
[DataMember(Order = 2)]
public List<Member> Members { get; set; }
}
}
Puis j'ai créé un objet de test comme suit:
var list = new List<V1.Member> { new V1.Member { Name = "Foo" }, new V1.Member { Name = "Bar" } };
var v1 = new V1.RootObject { MainMember = list[0], Members = list };
Notez que la fois de MainMember
objet Foo
est appelé deux fois, et une fois dans la liste Members
.
Quand je sérialisé cela en utilisant DataContractSerializer
, j'ai le code XML suivant:
<Root xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="Question45008433">
<MainMember z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<Name>Foo</Name>
</MainMember>
<Members>
<Member z:Ref="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" />
<Member z:Id="i2" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<Name>Bar</Name>
</Member>
</Members>
</Root>
Notez que l'objet Foo
est entièrement sérialisé quand il est premier sérialisé <MainMember>
, après quoi il est donné un attribut z:Id="i1"
. Lorsque des références ultérieures sont rencontrées pendant la sérialisation, seule une référence est sérialisée via z:Ref="i1"
.
Ensuite, j'ai décidé que le membre de données MainMember
était inutile et obsolète il:
namespace V2
{
[DataContract(Name = "Member", Namespace = "Question45008433", IsReference = true)]
public class Member
{
[DataMember]
public string Name { get; set; }
}
[DataContract(Name = "Root", Namespace = "Question45008433")]
public class RootObject
{
[DataMember(Order = 2)]
public List<Member> Members { get; set; }
}
}
Maintenant, si j'essaie de désérialiser le XML original en utilisant ce contrat modifié, je reçois l'exception même que vous voyez:
System.Runtime.Serialization.SerializationException: Deserialized object with reference id 'i1' not found in stream.
at System.Runtime.Serialization.XmlObjectSerializerReadContext.GetExistingObject(String id, Type type, String name, String ns)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.TryHandleNullOrRef(XmlReaderDelegator reader, Type declaredType, String name, String ns, Object& retObj)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, DataContract& dataContract)
Pourquoi cela se produit-il? Cela se produit parce que le membre de données obsolète est venu avant les membres de données restants. Ainsi, lors de la désérialisation, l'élément de définition est ignoré et ignoré, et les références suivantes ne peuvent pas être résolues.
La solution consiste à rajouter le membre de données d'origine en tant que propriété synthétique faux privée qui ne fait rien et retourne toujours null
:
namespace V3
{
[DataContract(Name = "Member", Namespace = "Question45008433", IsReference = true)]
public class Member
{
[DataMember]
public string Name { get; set; }
}
[DataContract(Name = "Root", Namespace = "Question45008433")]
public class RootObject
{
[DataMember(EmitDefaultValue = false, Order = 1)]
Member MainMember
{
get
{
return null;
}
set
{
// Do nothing
}
}
[DataMember(Order = 2)]
public List<Member> Members { get; set; }
}
}
Le XML d'origine peut maintenant être désérialisée avec succès parce que, lors de la désérialisation, les données Le sérialiseur de contrat lui-même maintient une table de consultation de tous les éléments de référence par leur nom. Toutefois, l'élément z:Ref="i1"
est ajouté uniquement lorsqu'il est rencontré s'il correspond à un membre actuellement valide. Et, parce que EmitDefaultValue = false
, l'élément obsolète n'apparaîtra plus lors de la sérialisation.
Copie possible de [Comment puis-je ignorer une propriété lors de la sérialisation à l'aide de DataContractSerializer?] (Https://stackoverflow.com/questions/1791946/how-can-i-ignore-a-property-when-serializing-using -the-datacontrerserializer) –
@WimOmbelets Veuillez lire les deux questions. Ils sont deux sujets différents ... – jannagy02
Nous avons besoin de voir un [mcve] de votre problème. Il semble que quelque chose ne va pas avec [suivi de référence d'objet] (https://stackoverflow.com/questions/1037201/isreference-property-in-data-contract). Par exemple, vous avez peut-être obsolète un membre de données où un objet est défini, ainsi une référence ultérieure à l'objet dans le XML via un attribut '" z: Ref "' échoue. – dbc