我正在尝试反序列化我在另一个时间序列化的XML文档。我用它来存储配置文件。
这是我的代码:
namespace OrderTracker
{
[Serializable]
public class AutofillValues
{
private string fileName = Directory.GetCurrentDirectory() + "\\bin\\settings.db";
public ComboBox.ObjectCollection Vendors { get; set; }
public ComboBox.ObjectCollection Products { get; set; }
public ComboBox.ObjectCollection Companies { get; set; }
public void save(AutofillValues afv)
{
if (!File.Exists(fileName))
{
FileStream fs = File.Create(fileName);
fs.Close();
}
XmlSerializer x = new XmlSerializer(typeof(AutofillValues));
TextWriter writer = new StreamWriter(fileName);
x.Serialize(writer, afv);
writer.Close();
}
public AutofillValues load()
{
XmlSerializer x = new XmlSerializer(typeof(AutofillValues));
TextReader file = new StreamReader(fileName);
AutofillValues av = (AutofillValues)x.Deserialize(file);
file.Close();
return av;
}
}
}
我在尝试反序列化文件时收到的错误消息是这样的;
未处理的类型' System.InvalidOperationException'发生在System.Xml.dll中 附加信息:XML文档中存在错误(2,2)。*
这是XML文档:
<?xml version="1.0" encoding="utf-8"?>
<AutofillValues xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Vendors>
<anyType xsi:type="xsd:string">Test Vendor</anyType>
</Vendors>
<Products>
<anyType xsi:type="xsd:string">Test Product</anyType>
</Products>
<Companies>
<anyType xsi:type="xsd:string">Test Company</anyType>
</Companies>
</AutofillValues>
如何反序列化XML文件并取回序列化数据?
答案 0 :(得分:1)
我刚刚更改了这部分,它对我有用。 JSFiddle Demo
答案 1 :(得分:0)
您无法反序列化XML,因为类ComboBox.ObjectCollection
没有标准(无参数)构造函数。这是XmlSerializer类的限制,如此SO post中所述。
然而,当前代码存在另一个问题 - 即使反序列化以某种方式工作,仍然需要将集合分配给ComboBox控件,而解串器仍然无法执行。
我建议不要使用ComboBox.ObjectCollection
类来存储项目,而是建议使用对象的数组或列表(如@kenlacoste建议的那样) 。可以使用这些集合轻松插入到ComboBox中
comboBox.Items.AddRange(arrayOfObjects)
方法。
另一种重构是提取数据类的序列化逻辑。目前,save
和load
数据令人困惑,因为我认为你想要保存/填充调用者对象:
object.save(object);
- 您可以在保存方法中使用this
关键字object = object.load();
- 此处相同,无需返回值,使用this
关键字填充现有属性更改后的代码:
public class AutofillValues
{
private string fileName = @"d:\settings.db";
public object[] Vendors { get; set; }
public object[] Products { get; set; }
public object[] Companies { get; set; }
public void save()
{
XmlSerializer x = new XmlSerializer(typeof(AutofillValues));
// with using there is no need to close the writer explicitely
// second parameter - file is created if it does not exist
using (var writer = new StreamWriter(fileName, false))
{
x.Serialize(writer, this);
}
}
public void load()
{
XmlSerializer x = new XmlSerializer(typeof(AutofillValues));
AutofillValues av = (AutofillValues)x.Deserialize(new StreamReader(fileName));
this.Companies = av.Companies;
this.Vendors = av.Vendors;
this.Products = av.Products;
}
}
IMO修改后的代码更易于阅读和理解:
var afv = new AutofillValues();
afv.load();
//use avf.Products
// or afv.save();
我还建议提取需要在额外课程中保存的数据,例如:
[Serializable]
public class AutofillValuesData
{
public Object[] Vendors { get; set; }
public Object[] Products { get; set; }
public Object[] Companies { get; set; }
}
在课程AutofillValues
中删除三个属性,只留一个:
public AutofillValuesData Data { get; set; }
然后可以修改逻辑以从填充的数据对象填充ComboBox控件。这样,您的数据就不会硬连线到UI,这将使代码更易于维护。您可以使用AutoMapper之类的帮助程序删除重复代码(例如mappig objA.Vendors
到objB.Vendors
)。