在保持对象引用的同时序列化C#对象

时间:2015-07-21 19:33:53

标签: c# .net serialization save

所以我有多个自定义类,它们在实例中引用其他类。我知道序列化一般如何工作,但我如何处理对象引用?目标是将对象保存在xml或二进制文件中,以便以后可以恢复状态。

在这个简化的示例中,人员由id标识,并且有一个名为friends的其他Person对象的列表。

for filename in ftp.nlst(filematch):
    target_file_name = os.path.basename(filename)
    with open(target_file_name ,'wb') as fhandle:
        ftp.retrbinary('RETR %s' % filename, fhandle.write)
    the_files.append(target_file_name)
    mtime = modification_date(target_file_name)
    mtime_str_for_file = str(mtime)[0:10] + str(mtime)[11:13] + str(mtime)[14:16]    + str(mtime)[17:19] + str(mtime)[20:28]#2014-12-11 15:08:00.338415.
    sorted_xml_files = [file for file in glob.glob(os.path.join('\\\\Storage\\shared\\', '*.xml'))]
    sorted_xml_files.sort(key=os.path.getmtime)
    last_file = sorted_xml_files[-1]
    file_is_the_same = filecmp.cmp(target_file_name, last_file)
    if not file_is_the_same:
        print 'File changed!'
        copyfile(target_file_name, '\\\\Storage\\shared\\'+'datebreaks'+mtime_str_for_file+'.xml') 
    else:
        print 'File '+ last_file +' hasn\'t changed, doin nothin'
        continue

如何序列化和反序列化此示例并保持对象引用不变?此外,我认为如果反序列化试图恢复对尚未被反序列化的人的引用,那么反序列化可能会非常棘手。

2 个答案:

答案 0 :(得分:4)

[XmlRootAttribute("Person")]
public class Person{
    [XmlAttribute("_id")]
    public int id;
    [XmlElement("friends")]
    public List<Person> friends;
}

然后使用XmlSerializer类创建xml文件和/或对象 https://msdn.microsoft.com/en-us/library/58a18dwa.aspx

答案 1 :(得分:1)

如果您搭载WCF并使用DataContract属性并设置IsReference = true,则可以跟踪引用,然后您需要使用DataContractSerializer来序列化数据。

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;

namespace SandboxConsole
{
    internal class Program
    {
        public static void Main()
        {
            var bob = new Person {Id = 0};
            var scott = new Person {Id = 1};
            var dave = new Person {Id = 2};

            bob.Friends.Add(scott);
            bob.Friends.Add(dave);
            scott.Friends.Add(dave);

            var people = new List<Person>();
            people.Add(bob);
            people.Add(scott);
            people.Add(dave);

            using (var fs = File.Create("Test.xml"))
            {
                var ser = new DataContractSerializer(typeof(List<Person>));
                ser.WriteObject(fs, people);
            }

            List<Person> people2;
            using (var fs = File.OpenRead("Test.xml"))
            {
                var ser = new DataContractSerializer(typeof(List<Person>));
                people2 = (List<Person>)ser.ReadObject(fs);
            }

            Console.WriteLine("Are these daves the same dave?");
            Console.WriteLine("List dave, bob's friend - {0}", ReferenceEquals(people2[2], people2[0].Friends[1]));
            Console.WriteLine("Bob's firend, scott's friend - {0}", ReferenceEquals(people2[0].Friends[1], people2[1].Friends[0]));
            Console.ReadLine();
        }
    }

    [DataContract(IsReference = true)]
    public class Person
    {
        public Person()
        {
            Friends = new List<Person>();
        }

        [DataMember]
        public int Id { get; set; }

        [DataMember]
        public List<Person> Friends { get; private set; }
    }
}

尝试使用IsRefrence = false运行上述测试程序或不使用参数(默认为false),它将输出false作为同一对象的测试。但是,如果将其设置为IsRefrence = false,则会输出true作为同一对象的测试。

编辑:一个重要提示,我无法让RefrenceEquals(people[0], people2[0])输出true