DataContractSerializer:在流中找不到引用 id 'xyz' 的反序列化对象。如何恢复数据?

Posted

技术标签:

【中文标题】DataContractSerializer:在流中找不到引用 id \'xyz\' 的反序列化对象。如何恢复数据?【英文标题】:DataContractSerializer: Deserialized object with reference id 'xyz' not found in stream. How to recover data?DataContractSerializer:在流中找不到引用 id 'xyz' 的反序列化对象。如何恢复数据? 【发布时间】:2012-08-29 19:14:02 【问题描述】:

我已使用 DataContractSerializer 将对象数组保存到文件中。直到最近我开始收到以下消息时,它一直运行良好。

Deserialized object with reference id '15' not found in stream
   bei System.Runtime.Serialization.XmlObjectSerializerReadContext.GetExistingObject(String id, Type type, String name, String ns)
   bei ReadAbgleichSettingsFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
   bei System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
   bei System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
   bei System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
   bei System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
   bei ReadUnitOfTestFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
   bei System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
   bei System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
   bei System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
   bei System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
   bei ReadArrayOfBaseModuleFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )
   bei System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
   bei System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
   bei System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
   bei System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
   bei System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   bei System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   bei System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlReader reader)
   bei Pruef.Net.Model.ModuleManager.LoadModules() in D:\\my_workspaces\\visualstudioprojects\\Pruef.Net\\Pruef.Net\\PruefMvvm\\Model\\ModuleManager.cs:Zeile 626.

问题似乎与 AbgleichSettings 类有关。

    [DataContract(Name = "AbgleichSettings")]
public class AbgleichSettings

    #region PROPERTIES
    /// <summary>
    /// Enable feature
    /// </summary>
    [DataMember(Name = "IsEnabled")]
    public bool IsEnabled  get; set; 

    /// <summary>
    /// Display units after value
    /// </summary>
    [DataMember(Name="Units", IsRequired=false)]
    public string Units  get; set; 

    /// <summary>
    /// Multiply value by factor
    /// </summary>
    [DataMember(Name = "Factor")]
    public double Factor  get; set; 

    /// <summary>
    /// Show decimal places 0-3
    /// </summary>
    [DataMember(Name = "DecimalPlaces")]
    public int DecimalPlaces  get; set; 
    #endregion

    [OnDeserializing]
    void OnDeserializing(StreamingContext context)
    
        IsEnabled = false;
        Units = "";
        Factor = 1;
        DecimalPlaces = 0;
    

    public AbgleichSettings()
    
        IsEnabled = false;
        Units = "";
        Factor = 1;
        DecimalPlaces = 0;
    

注意后来在我试图解决问题时添加了 DataMember.Name 属性。

我查看了 XML,发现 Id="15" 的对象是一个 Comment 元素,它是不同类中的字符串属性。

<Header>
  <ChangeInfo z:Id="14">
    <Author i:nil="true" />
    <Comment z:Id="15"></Comment>
    <Date>0001-01-01T00:00:00</Date>
  </ChangeInfo>
</Header>
....
<Abgleich z:Id="34">
  <DecimalPlaces>0</DecimalPlaces>
  <Factor>1</Factor>
  <IsEnabled>false</IsEnabled>
  <Units z:Ref="15" i:nil="true" />
</Abgleich>

** 序列化器 **

return new DataContractSerializer(Modules.GetType(), null,
                int.MaxValue /*maxItemsInObjectGraph*/,
                true /*ignoreExtensionDataObject*/,
                true /*preserveObjectReferences : this is where the magic happens */,
                null /*dataContractSurrogate*/);

这里可能出了什么问题?我该怎么做才能从这个错误中恢复?

谢谢!

【问题讨论】:

我希望您尝试仅使用 WCF 反序列化此 XML,并且您正在实例化的 DataContractSerializer 已将 preserveObjectReferences 参数设置为 true。此外,您看到的 id 15 并不是真正的“评论”属性,但我认为它指的是 XML 中的空字符串 @Amit - preserveObjectReferences 参数 is 设置为 true。 “仅使用 WCF 反序列化此 XML”是什么意思?我使用 DataContractSerializer 进行序列化和反序列化(参见编辑) 【参考方案1】:

经过一些实验,我能够让它再次工作,但我不明白到底是什么问题。

“ModuleHeader”类最初只有属性[Serializable],它的属性有属性[DataMember]。最近,我将 [DataContract] 添加到课程中(似乎合适),这就是导致问题的原因。在 OnSerialized 事件中,我注意到该实例尚未初始化,因此未创建缺少 Id 的对象。一旦我删除了 [DataContract] 属性,反序列化就会再次开始工作。

我将发布一个新问题...

【讨论】:

以上是关于DataContractSerializer:在流中找不到引用 id 'xyz' 的反序列化对象。如何恢复数据?的主要内容,如果未能解决你的问题,请参考以下文章

DataContractSerializer 不调用我的构造函数?

使用 DataContractSerializer 自定义序列化

DataContractSerializer - 如何将 xml 输出到字符串(而不是文件)

通过 DataContractSerializer 跳过 DataMember

使用 DataContractSerializer 时设置属性的初始值

使用 DataContractSerializer 和 XmlDictionaryWriter 序列化 JObject 后崩溃