自定义对象是可序列化但不可反序列化的
问题描述:
我通过为实例调用其自己的静态函数来获取具有某些属性的类的对象。如果存在XML文件,则该对象会尝试加载它并将其值添加到实例本身。然后它将再次保存XML,以防XML文件中缺少选项。自定义对象是可序列化但不可反序列化的
我创建了一个小型控制台应用程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using System.Xml;
namespace Test
{
public class Program
{
static void Main(string[] args)
{
TaskServerSettings s = TaskServerSettings.LoadNew();
}
}
public class TaskServerSettings : IEqualityComparer
{
#region SETTINGS PROPERTIES
public bool Enabled { get; set; }
public int CheckInterval { get; set; }
#endregion
#region CONSTRUCTORS AND METHODS
public TaskServerSettings()
{
this.init();
}
public TaskServerSettings(string settingsFile)
{
this.init();
if (settingsFile != null)
{
if (File.Exists(settingsFile))
{
this.Load(settingsFile);
}
this.Save(settingsFile);
}
}
private void init()
{
this.Enabled = true;
this.CheckInterval = 5000;
}
public void Absorb(TaskServerSettings newSettings)
{
this.Enabled = newSettings.Enabled;
this.CheckInterval = newSettings.CheckInterval;
}
public static TaskServerSettings LoadNew(string settingsFile = null)
{
if (settingsFile == null)
{
settingsFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.TrimEnd('\\')) + @"\TaskServerSettings.xml";
}
return new TaskServerSettings(settingsFile);
}
public bool Load(string settingsFile = null)
{
if (settingsFile == null)
{
settingsFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.TrimEnd('\\')) + @"\TaskServerSettings.xml";
}
if (!File.Exists(settingsFile))
{
throw new FileNotFoundException("Could not find \"" + settingsFile + "\" to load settings.");
}
bool result = false;
using (FileStream fs = new FileStream(settingsFile, FileMode.Open))
{
XmlSerializer xs = new XmlSerializer(this.GetType());
if (!xs.CanDeserialize(XmlReader.Create(fs)))
{
throw new XmlException("\"" + settingsFile + "\" does not have a valid TaskServerSettings XML structure.");
}
//try
//{ // +- InvalidOperationException - Error in XML document (0,0).
// v The root element is missing.
this.Absorb(xs.Deserialize(fs) as TaskServerSettings);
result = true;
//}
//catch { }
}
return result;
}
public bool Save(string settingsFile = null)
{
if (settingsFile == null)
{
settingsFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.TrimEnd('\\')) + @"\TaskServerSettings.xml";
}
bool result = false;
using (FileStream fs = new FileStream(settingsFile, FileMode.Create))
{
XmlSerializer xs = new XmlSerializer(this.GetType());
try
{
xs.Serialize(fs, this);
result = true;
}
catch { }
}
return result;
}
#endregion
public bool Equals(TaskServerSettings settingsToCompare)
{
if (this.Enabled != settingsToCompare.Enabled ||
this.CheckInterval != settingsToCompare.CheckInterval)
{
return false;
}
return true;
}
bool IEqualityComparer.Equals(object x, object y)
{
return x.Equals(y);
}
int IEqualityComparer.GetHashCode(object obj)
{
throw new NotSupportedException();
}
}
}
写其默认属性值的对象在第一次运行的工作原理相当不错。 XML文件看起来是这样的,那么:
<?xml version="1.0"?>
<TaskServerSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Enabled>true</Enabled>
<CheckInterval>5000</CheckInterval>
</TaskServerSettings>
但是,反序列化的第二次运行相同的文件会导致错误时,它会尝试加载在 xs.Deserialize(fs) as TaskServerSettings
文件。
InvalidOperationException - Error in XML document (0,0).
The root element is missing.
我已经试图避免静态方法,并试图new
以及我已经试图删除IEqualityComparer
父+最后的三种方法。没有成功。
我想知道,这个错误是什么原因?
答
当你执行该语句:
if (!xs.CanDeserialize(XmlReader.Create(fs)))
它开始读取数据流。所以当你稍后调用Deserialize
时,该流不在开始处,所以反序列化失败。您需要通过设置倒带流fs.Position = 0
当!而已。谢谢。 =) – modiX 2013-03-19 13:49:02