.NET XML序列化和空集合

时间:2010-01-26 23:41:08

标签: c# .net serialization collections xml-serialization

我有一个包含一些集合的类,我想将这个类的实例序列化为XML,而不必将集合初始化为空,而不必实现IXmlSerializable。我不在乎它是否创建空元素,或者根本不创建元素。只需它可以工作而无需为每个基于集合的属性初始化集合。

我已经查看了我可以用它来装饰属性的所有XML属性,并且没有取得任何成功。这似乎是一个简单的事情,可以有一个元素或根本没有。然后,当它被反序列化时,它会将它们留空或忽略它们的周期。

以下是用于解决此问题的类的简单版本。使用this和defaults会得到一个异常“对象引用未设置为对象的实例”,因为集合为null;

public class MyClass
{
    public string Name { get; set; }
    public bool IsAlive { get; set; }
    public List<Car> Cars { get; set; }
    public List<Home> Homes { get; set; }
    public List<Pet> Pets { get; set; }

    public void ToXmlFile(string fileName)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
        TextWriter writer = new StreamWriter(fileName);
        serializer.Serialize(writer, this);
        writer.Close();
    }
}

修改 感谢帮助人员,事实证明问题出在我的GetHashCode方法中,该方法没有正确处理null。一旦我修好了这一切都很好。我标记了第一个回答是正确的。对不起红鲱鱼,但与你们一起工作确实有所帮助。

4 个答案:

答案 0 :(得分:5)

您无需初始化集合以将类序列化为XML。这是一个简单的程序来演示:

class Program
{
    static void Main(string[] args)
    {
        MyClass c = new MyClass() { Name = "Test", IsAlive = true };
        XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
        using (MemoryStream ms = new MemoryStream())
        {
            serializer.Serialize(ms, c);
            Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
        }
        Console.ReadLine();
    }
}

这将打印以下输出:

<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>Test</Name>
  <IsAlive>true</IsAlive>
</MyClass>

换句话说,null集合属性的行为与任何其他null属性的行为相同 - 它们根本不会被序列化(除非您更改默认值,我没有)

答案 1 :(得分:0)

您可以在没有问题的情况下对此进行序列化,只需在序列化extraTypes参数时发送汽车,家庭和宠物的类型。

答案 2 :(得分:0)

你在(反)序列化期间提到了一个例外;你有什么应该工作好(至少,根据你如何定义问题)。我想知道你是否真的有:

public class MyClass
{
    public string Name { get; set; }
    public bool IsAlive { get; set; }
    public List<Car> Cars { get; private set; }
    public List<Home> Homes { get; private set; }
    public List<Pet> Pets { get; private set; }
}

(并不罕见不想要公共制定者)

嗯,XmlSerializer对此很挑剔;你需要一个公共的二传手,或者(最近有人指出)没有 setter;例如:

public class MyClass
{
    public string Name { get; set; }
    public bool IsAlive { get; set; }
    private readonly List<Car> cars = new List<Car>();
    public List<Car> Cars { get { return cars; } }
    private readonly List<Home> homes = new List<Home>();
    public List<Home> Homes { get { return homes; } }
    private readonly List<Pet> pets = new List<Pet>();
    public List<Pet> Pets { get { return pets; } }
}

答案 3 :(得分:0)

我认为将XMLSerialisation方法的返回类型设置为 bool 将允许您以更安全的方式处理错误,而不是当前方法:

public bool ToXmlFile(string fileName)
{
    if(fileName != "")
    {
       XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
       TextWriter writer = new StreamWriter(fileName);
       serializer.Serialize(writer, this);
       writer.Close();
       return true;
    }
    return false;
}

然后可以这样使用:

if(ToXMLFile)
{
     MessageBox.Show("Save Succesful");
}
else
(
     MessageBox.Show("Save unsuccesful");
)

这仅仅是一个粗略的例子,但是我在加载或保存数据时在我自己的应用程序中使用了类似的方法,它运行良好,也是最终用户的良好视觉指示器。