你能控制DataContractSerializer反序列化的深度吗?

时间:2009-01-05 14:57:16

标签: .net serialization xml-serialization datacontractserializer

我有一个相当大的对象图,我通过DataContractSerializer序列化到一个文件。我现在想要向用户提供这些文件的列表以供选择。在此列表中,我想显示有关该文件的一些详细信息,这些属性是根对象的属性。我不想将整个图形加载到内存中,因为我只对显示根节点的属性感兴趣。

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

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

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

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

其次,它们比我想做的更持久。最后,我确实希望反序列化整个文件,而不是在此时。我正在尝试显示用户将从中进行导入的文件摘要列表。在进口过程中,我将需要所有的孩子和孙子。在第1步中它只是矫枉过正。这些都是潜在的大文件,所以完全反序列化其中的几个,这样我才能显示它们的标题信息是行不通的。

希望能够解决对原始问题的任何困惑。

3 个答案:

答案 0 :(得分:1)

这就是你想要的方式。 DataContractSerializer旨在处理这种情况,在这种情况下,您必须从概念上相同的类型,但从CLR的角度来看,您希望彼此序列化的类型不同。

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

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

答案 1 :(得分: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;

}

答案 2 :(得分:-2)

您可以使用属性控制序列化。 阅读更多here