具有构造函数的列表的DotNet XmlSerializer

时间:2013-04-03 15:20:41

标签: .net deserialization xmlserializer

我在XmlSerializer中发现了一些意外行为。 如果取消列表中列表具有默认构造函数的对象列表,则也会附加列表。

任何人都知道如何解决这个问题? 这是一个例子。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace XmlSerialiserTest
{
    public class Schedule
    {
        public Schedule()
        {
            Days = new List<DayOfWeek>() { DayOfWeek.Monday };
            Time = DateTime.UtcNow;
        }
        public List<DayOfWeek> Days { get; set; }
        public DateTime Time { get; set; }
        public override string ToString()
        {
            return String.Format("{0},{1}", Time.ToShortTimeString(), string.Join(",", Days));
        }

    }

    public class Schedules
    {
        public List<Schedule> ScheduleList { get; set; }
        public Schedules()
        {
            ScheduleList = new List<Schedule>();
        }
        public override string ToString()
        {
            return string.Join(":",ScheduleList);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            // create a our list of Schedule with one schedule in
            // default constructor will give us Monday by default
            Schedules schedulesOut = new Schedules();
            schedulesOut.ScheduleList.Add(new Schedule());
            // Save
            XmlSerializer s = new XmlSerializer(typeof(Schedules));
            TextWriter writer = new StreamWriter("C:\\xmltest.xml");
            s.Serialize(writer,schedulesOut);
            writer.Close();
            Console.WriteLine(schedulesOut);
            // Output is 15:09,Monday
            // Now saved to disk and read back

            TextReader reader = new StreamReader("C:\\xmltest.xml");
            Schedules schedulesIn = (Schedules)s.Deserialize(reader);
            Console.WriteLine(schedulesIn);
            // Output is 15:09,Monday,Monday
            // schedulesIn in now contains two Mondays ,not one as expected

        }
    }
}

2 个答案:

答案 0 :(得分:1)

将列表更改为数组。这按预期工作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace XmlSerialiserTest
{
    public class Schedule
    {
        public Schedule()
        {
           Days = new[] { DayOfWeek.Monday };
           Time = DateTime.UtcNow;
        }
        public DayOfWeek[] Days { get; set; }
        public DateTime Time { get; set; }
        public override string ToString()
        {
            return String.Format("{0},{1}", Time.ToShortTimeString(), string.Join(",",     Days));
    }

 }

public class Schedules
{
    public List<Schedule> ScheduleList { get; set; }
    public Schedules()
    {
        ScheduleList = new List<Schedule>();
    }
    public override string ToString()
    {
        return string.Join(":",ScheduleList);
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        // create a our list of Schedule with one schedule in
        // default constructor will give us Monday by default
        Schedules schedulesOut = new Schedules();
        schedulesOut.ScheduleList.Add(new Schedule());
        // Save
        XmlSerializer s = new XmlSerializer(typeof (Schedules));
        TextWriter writer = new StreamWriter("C:\\xmltest.xml");
        s.Serialize(writer, schedulesOut);
        writer.Close();
        Console.WriteLine(schedulesOut);
        // Output is 15:09,Monday
        // Now saved to disk and read back

        TextReader reader = new StreamReader("C:\\xmltest.xml");
        Schedules schedulesIn = (Schedules) s.Deserialize(reader);
        Console.WriteLine(schedulesIn);
        // Output is 15:09,Monday,Monday
        // schedulesIn in now contains two Mondays ,not one as expected

    }
}

}

答案 1 :(得分:1)

这是预期的行为。为了能够“实例化”您的对象,它将始终调用无参数构造函数。实际上,为了能够反序列化,你总是需要一个无参数的构造函数。

因为构造函数创建了列表并添加了Monday作为值,所以反序列化的对象默认包含此值。

通过你确实可以使用数组,我建议关注分离并使用工厂方法手动创建Schedule个对象。然后工厂可以用星期一初始化第一个值。

请注意,您需要使用public parameterless构造函数进行反序列化。通常在使用工厂模式时,您需要限制对构造函数的访问。