【问题标题】:Deserialization of serialized data fails序列化数据的反序列化失败
【发布时间】:2015-08-11 16:20:29
【问题描述】:

我正在尝试反序列化一个我也在另一个时间序列化的 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.Xml.dll 中出现“System.InvalidOperationException”类型的未处理异常 附加信息: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 文件并取回序列化数据?

【问题讨论】:

  • 您不能将其反序列化 - 这是 XmlSerializer 的限制,如 SO post 中所述。
  • 忘了提——问题是ComboBox.ObjectCollection 没有无参数构造函数——XmlSerializer 需要一个没有参数的默认构造函数!

标签: c# xml serialization deserialization


【解决方案1】:

我刚刚更改了这部分,它对我有用。

【讨论】:

  • 哇...谢谢,我没想过只使用基本的对象列表。这对我有用,非常感谢!
【解决方案2】:

您不能反序列化 XML,因为类 ComboBox.ObjectCollection 没有标准(无参数)构造函数。这是 XmlSerializer 类的限制,如 SO post 中所述。

但是,您当前的代码还有另一个问题 - 即使反序列化以某种方式起作用,您仍然需要将集合分配给 ComboBox 控件,而反序列化程序仍然无法做到这一点。

我建议不要使用ComboBox.ObjectCollection 类来存储项目,而是使用arraylist 对象(如@kenlacoste 建议的那样)。这样的集合可以很容易地插入到 ComboBox 使用 comboBox.Items.AddRange(arrayOfObjects) 方法。

另一个重构是提取数据类的序列化逻辑。目前它对saveload 的数据感到困惑,因为我假设你想保存/填充调用者对象:

  • 保存:object.save(object); - 您可以在保存方法中使用this 关键字
  • load: 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.VendorsobjB.Vendors)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-02
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多