C# - 如何xml反序列化对象本身?

dav*_*led 8 c# serialization

public class Options
    {
        public FolderOption FolderOption { set; get; }

        public Options()
        {
            FolderOption = new FolderOption();
        }


        public void Save()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Options));
            TextWriter textWriter = new StreamWriter(@"C:\Options.xml");
            serializer.Serialize(textWriter, this);
            textWriter.Close();
        }

        public void Read()
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(Options));
            TextReader textReader = new StreamReader(@"C:\Options.xml");
            //this = (Options)deserializer.Deserialize(textReader);
            textReader.Close();

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我设法保存没有问题,FolderOption的所有成员都被反序列化.但问题是如何阅读它?行 - // this =(Options)deserializer.Deserialize(textReader); 不行.

编辑:这个问题的任何解决方案?我们可以达到同样的目的而不分配给它吗?这是将Options对象反序列化为Option.我懒得去做物业.在最高级别上执行将节省大量精力.

Joe*_*orn 19

将您的.Read()方法构建为返回读取对象的静态函数:

public static Options Read(string path)
{
    XmlSerializer deserializer = new XmlSerializer(typeof(Options));
    using (TextReader textReader = new StreamReader(path))
    {
        return (Options)deserializer.Deserialize(textReader);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后更改您的调用代码,而不是像这样:

Options myOptions = new Options();
myOptions.Read(@"C:\Options.xml");
Run Code Online (Sandbox Code Playgroud)

你做这样的事情:

Options myOptions = Options.Read(@"C:\Options.xml");
Run Code Online (Sandbox Code Playgroud)

不同的是,不可能有一个没有一些数据的Options对象.


ama*_*int 11

如果您的Options类型是结构,这将起作用,因为您可以更改结构本身.

如果Options是类(引用类型),则无法在该实例中分配引用类型的当前实例.建议你编写一个帮助类,并将Read和Save方法放在那里,就像这样

     public class XmlSerializerHelper<T>
    {
        public Type _type;

        public XmlSerializerHelper()
        {
            _type = typeof(T);
        }


        public void Save(string path, object obj)
        {
            using (TextWriter textWriter = new StreamWriter(path))
            {
                XmlSerializer serializer = new XmlSerializer(_type);
                serializer.Serialize(textWriter, obj);
            }

        }

        public T Read(string path)
        {
            T result;
            using (TextReader textReader = new StreamReader(path))
            {
                XmlSerializer deserializer = new XmlSerializer(_type);
                result = (T)deserializer.Deserialize(textReader);
            }
            return result;

        }
    }
Run Code Online (Sandbox Code Playgroud)

然后从调用者那里使用它来读取和保存对象,而不是从类中尝试它.

//In the caller

var helper=new XmlSerializerHelper<Options>();
var obj=new Options();

//Write and read
helper.Save("yourpath",obj);
obj=helper.Read("yourpath");
Run Code Online (Sandbox Code Playgroud)

并将XmlSerializerHelper放在Util的命名空间中,它是可重用的,可以使用任何类型.


Joh*_*ers 5

根据定义,对象不能反序列化自身:它已经存在,反序列化会创建该类型的新实例.

创建类的新的空实例有时是有意义的,然后用XML引入的信息填充它.该实例也可能"几乎是空的".例如,您可以执行此操作以加载用户首选项,或者通常,将实例重新设置为以前的方式.实例的"空"或"近空"状态将是该类的有效状态:它只是不知道它在持久化之前曾处于什么状态.


另外,我建议你养成实现"使用"块的习惯:

public void Save()
{
    XmlSerializer serializer = new XmlSerializer(typeof(Options));
    using (TextWriter textWriter = new StreamWriter(@"C:\Options.xml"))
    {
        serializer.Serialize(textWriter, this);
        // no longer needed: textWriter.Close();
    }
}

public void Read()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(Options));
    using (TextReader textReader = new StreamReader(@"C:\Options.xml"))
    {
        // no longer needed: textReader.Close();
    }
}
Run Code Online (Sandbox Code Playgroud)

这将确保即使抛出异常也会处理TextReaders.这就是不再需要Close调用的原因.