[英]C# Can't get my dictionary to serialize in XML
我正在做一个小项目,以学习如何在C#.NET中序列化对象。我创建了以下类,该类是我尝试序列化的类:
public class Object
{
private Dictionary<string, int> dictionaryStringInt;
public Object()
{
this.dictionaryStringInt = new Dictionary<string, int>();
}
public void AddToDictionary(string s, int i)
{
this.dictionaryStringInt.Add(s, i);
}
public List<DictionaryEntry> DictionaryStringInt
{
get
{
List<DictionaryEntry> list = new List<DictionaryEntry>();
foreach (KeyValuePair<string, int> element in dictionaryStringInt)
{
list.Add(new DictionaryEntry(element.Key, element.Value));
}
return list;
}
set
{
Dictionary<string, int> dictionary = new Dictionary<string, int>();
foreach (DictionaryEntry entry in value)
{
dictionary.Add(entry.Key, entry.Value);
}
dictionaryStringInt = dictionary;
}
}
public class DictionaryEntry
{
private string key;
private int value;
public DictionaryEntry()
{
this.key = string.Empty;
this.value = 0;
}
public DictionaryEntry(string key, int value)
{
this.key = key;
this.value = value;
}
[XmlAttribute("Key")]
public string Key
{
get
{
return key;
}
set
{
key = value;
}
}
[XmlText]
public int Value
{
get
{
return value;
}
set
{
this.value = value;
}
}
}
}
我在这里有这段代码可以完成工作:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.ClearTextBox();
SerialisationTest.Object @object = this.SetUpObject();
this.Serialize(@object);
@object = null;
@object = this.Deserialise(@"C:\Sources\SerialisationTest\test.xml");
this.textBox1.Text = @object.ToString();
this.DisplayXML(@object);
}
public void Serialize(SerialisationTest.Object @object)
{
XmlSerializer serializer = new XmlSerializer(typeof(SerialisationTest.Object));
using (TextWriter writer = new StreamWriter(@"C:\Sources\SerialisationTest\test.xml"))
{
serializer.Serialize(writer, @object);
}
}
public SerialisationTest.Object Deserialise(string path)
{
XmlSerializer serializer = new XmlSerializer(typeof(SerialisationTest.Object));
using (TextReader reader = new StreamReader(path))
{
return (SerialisationTest.Object)serializer.Deserialize(reader);
}
}
public void DisplayXML(SerialisationTest.Object @object)
{
XmlSerializer serializer = new XmlSerializer(typeof(SerialisationTest.Object));
using (StringWriter writer = new StringWriter())
{
serializer.Serialize(writer, @object);
this.textBox1.Text = writer.ToString();
}
}
public SerialisationTest.Object SetUpObject()
{
SerialisationTest.Object @object = new SerialisationTest.Object();
@object.AddToDictionary("1", 1);
@object.AddToDictionary("2", 2);
@object.AddToDictionary("3", 3);
return @object;
}
public void ClearTextBox()
{
this.textBox1.Text = "";
}
}
现在,这是我在文本框中看到的结果:
<?xml version="1.0" encoding="utf-16"?>
<Object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DictionaryStringInt />
</Object>
现在大多数代码只是我在尝试序列化。 但是后来我尝试序列化DictionaryStringInt
并在MSDN上看到字典无法序列化。 因此,我尝试通过使属性返回DictionaryEntry
列表并将该列表转换为setter中的字典来欺骗序列化器。 但是如您所见, DictionaryStringInt
的数据未序列化。 我希望收到以下信息:
<?xml version="1.0" encoding="utf-16"?>
<Object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DictionaryStringInt>
<DictionaryEntry Key="1">1</DictionaryEntry>
<DictionaryEntry Key="2">2</DictionaryEntry>
<DictionaryEntry Key="3">3</DictionaryEntry>
</DictionaryStringInt>
</Object>
有谁知道如何实现这一目标? (顺便说一句,我知道如果在反序列化字典时在XML中有多个相同的键,我会得到类似KeyAlreadyPresentException之类的东西,这是一种行为要求)
谢谢!
编辑
我刚刚发现"C:\\Sources\\SerialisationTest\\test.xml"
包含正确的结果。
因此,使用StringWriter进行反序列化或显示序列化似乎存在问题。
我做错什么了吗?
编辑2
简化代码
编辑3
我看了评论中链接的答案,我想我知道了怎么回事...在其中一个答案中,有一条评论指出,将不会调用setter,而应使用数组。 我正在调查这个。
问题在于,在反序列化期间,您将丢失代理List<DictionaryEntry> DictionaryStringInt
属性的内容。 解决方法是将其更改为数组:
DictionaryEntry [] DictionaryStringInt
{
get
{
if (dictionaryStringInt == null)
return null;
List<DictionaryEntry> list = new List<DictionaryEntry>();
foreach (KeyValuePair<string, int> element in dictionaryStringInt)
{
list.Add(new DictionaryEntry(element.Key, element.Value));
}
return list.ToArray();
}
set
{
if (value == null)
return;
Dictionary<string, int> dictionary = new Dictionary<string, int>();
foreach (DictionaryEntry entry in value)
{
dictionary.Add(entry.Key, entry.Value);
}
dictionaryStringInt = dictionary;
}
}
有关为什么List<DictionaryEntry>
代理属性在反序列化期间失败的解释,请参见无法使用XML Deserializer将XML反序列化为列表 。 如此处所述:
XmlSerializer
调用getter获取列表。 如果为null,它将分配一个列表并通过setter进行设置。 在读取列表时,它会在一些局部变量中保留列表。
它反序列化每个列表元素,并将其添加到它持有的列表中。
就是这样。 此后再也不会调用包含类的list属性设置器 。 因此,列表的内容永远不会填充到您的字典中。
但是,由于数组一旦分配就无法调整大小,因此必须在读取和反序列化其内容后对其进行分配和重新设置。 因此,数组属性可以在反序列化期间充当代理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.