我在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
}
}
}
答案 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构造函数进行反序列化。通常在使用工厂模式时,您需要限制对构造函数的访问。