2

我有一个相当大的对象图,我已经通过DataContractSerializer序列化到一个文件。我现在想把这些文件列表提供给用户选择。在这个列表中,我想显示一些关于该文件的细节,这些是根对象的属性。我不想将整个图加载到内存中,因为我只想显示根节点的属性。你可以控制DataContractSerializer反序列化的深度吗?

有谁知道一种方法来控制反序列化的“深度”,以便我可以从文件中拉出根对象并跳过子节点?我宁愿避免将该文件视为原始XML,因为我没有在其他任何地方进行任何原始XML操作,而这将是我必须保持同步的另一个代码分支。

我现在唯一的想法是创建一个兼容的“摘要”对象,其中只包含我感兴趣的属性,而不包含任何子项,并将该文件反序列化为该文件。这应该跳过子节点,因为它们与摘要对象无关。

有没有更好的方法来实现这个目标?

更新/澄清:属性不是我正在寻找的答案。首先,当对象第一次序列化时,它们将防止“额外”属性在文件中结束。

其次,它们比我想要做的更持久。最终,我确实想对整个文件进行反序列化,而不是在这个时候。我正试图显示用户可以选择进行导入的文件摘要列表。在进口过程中,我需要所有的孩子和孙子。这只是在步骤1中矫枉过正。这些是可能的大文件,因此完全反序列化它们中的几个,以便我可以显示它们的标题信息不会起作用。

希望能够澄清关于原始问题的任何混淆。

回答

1

这几乎是你想要做到的。 DataContractSerializer是为了处理这种情况,你必须在概念上相同的类型,但CLR的观点不同,你想要序列化到彼此的类型。

鉴于此,只需创建具有您想要序列化的类似属性子集的对象,并将该类型传递给DataContractSerializer。

确保在设置DataContract属性的属性的“摘要”类型(以及您公开的子级上的任何DataMember属性或DataContract属性)上,特别是名称和名称空间属性以反映名称和名称空间非摘要类型(因为这些必须匹配)。

-2

你可以通过使用属性来控制序列化。 了解更多here

1

我的第一个建议是,如果你只是想从根节点中提取一些细节,就要做XML操作。另一种可能性,虽然我不知道性能影响,但是使用DataContractSerializer的版本控制功能来解决这个问题。在您的数据合同上,将摘要中除您需要的字段以外的每个字段标记为“可选”。然后,将数据合同作为另一个类复制,而忽略可选字段。反序列化到新的较小的数据合同。

class Program 
{ 
    static void Main(string[] args) 
    { 
     Person a = new Person(); 
     Person b = new Person(); 
     a.Name = "Mike"; 
     b.Name = "Joe"; 
     b.Parent = a; 

     DataContractSerializer dtc = new DataContractSerializer(typeof(Person)); 

     StringBuilder sb = new StringBuilder(); 
     using (XmlWriter xr = XmlWriter.Create(sb)) 
     { 
      dtc.WriteObject(xr, b); 
     } 

     object n; 

     DataContractSerializer dtc2 = new DataContractSerializer(typeof(TinyPerson)); 

     using (XmlReader xr = XmlReader.Create(new StringReader(sb.ToString()))) 
     { 
      n = dtc2.ReadObject(xr); 
     } 

    } 
} 

[DataContract(Name="Person")] 
public class Person 
{ 
    [DataMember] 
    public string Name; 

    [DataMember(IsRequired=false)] 
    public Person Parent; 
} 


[DataContract(Name = "Person")] 
public class TinyPerson 
{ 
    [DataMember] 
    public string Name; 

} 
相关问题