小编典典

.net XML序列化-存储参考而不是对象副本

c#

  • 在.Net / C#应用程序中,我具有相互引用的数据结构。
  • 当我序列化它们时,.Net会使用单独的对象副本序列化所有引用。
  • 在下面的示例中,我尝试序列化为“人”数组
  • “人员”可能引用了另一个人。

    public class Person
    

    {
    public string Name;
    public Person Friend;
    }

    Person p1 = new Person();
    p1.Name = “John”;

    Person p2 = new Person();
    p2.Name = “Mike”;

    p1.Friend = p2;

    Person[] group = new Person[] { p1, p2 };
    XmlSerializer ser = new XmlSerializer(typeof(Person[]));
    using (TextWriter tw = new StreamWriter(“test.xml”))
    ser.Serialize(tw,group );

    //above code generates following xml



    John

    Mike



    Mike

  • 在上面的代码中,相同的“ Mike”对象位于两个位置,因为同一对象有两个引用。

  • 反序列化时,它们变成两个不同的对象,在序列化时它们不是精确的状态。

  • 我想避免这种情况,并且序列化xml中只有对象的副本,并且所有引用都应引用此副本。反序列化之后,我想找回原来的数据结构。
  • 可能吗 ?

阅读 257

收藏
2020-05-19

共1个答案

小编典典

XmlSerializer是不可能的。您可以使用PreserveObjectReferences属性使用DataContractSerializer实现此目的。您可以查看这篇解释详细信息的帖子

这是一个示例代码:

public class Person
{
    public string Name;
    public Person Friend;
}

class Program
{
    static void Main(string[] args)
    {
        Person p1 = new Person();
        p1.Name = "John";

        Person p2 = new Person();
        p2.Name = "Mike";
        p1.Friend = p2;
        Person[] group = new Person[] { p1, p2 };

        var serializer = new DataContractSerializer(group.GetType(), null, 
            0x7FFF /*maxItemsInObjectGraph*/, 
            false /*ignoreExtensionDataObject*/, 
            true /*preserveObjectReferences : this is where the magic happens */, 
            null /*dataContractSurrogate*/);
        serializer.WriteObject(Console.OpenStandardOutput(), group);
    }
}

这将产生以下XML:

<ArrayOfPerson z:Id="1" z:Size="2" xmlns="http://schemas.datacontract.org/2004/07/ToDelete" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
    <Person z:Id="2">
        <Friend z:Id="3">
            <Friend i:nil="true"/>
            <Name z:Id="4">Mike</Name>
        </Friend>
        <Name z:Id="5">John</Name>
    </Person>
    <Person z:Ref="3" i:nil="true"/>
</ArrayOfPerson>

现在在构造函数中设置PreserveObjectReferencesfalse,您将获得以下信息:

<ArrayOfPerson xmlns="http://schemas.datacontract.org/2004/07/ToDelete" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Person>
        <Friend>
            <Friend i:nil="true"/>
            <Name>Mike</Name>
        </Friend>
        <Name>John</Name>
    </Person>
    <Person>
        <Friend i:nil="true"/>
        <Name>Mike</Name>
    </Person>
</ArrayOfPerson>

值得一提的是,以这种方式生成的XML不可互操作,只能使用DataContractSerializer进行反序列化(与BinaryFormatter相同的说明)。

2020-05-19