【问题标题】:C# Can't get my dictionary to serialize in XMLC# 无法让我的字典在 XML 中序列化
【发布时间】:2017-05-19 04:38:57
【问题描述】:

我正在做一个小项目来学习如何在 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 上看到 Dictionary 无法序列化。所以我试图通过让属性返回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 并且我应该使用数组。我正在研究这个。

【问题讨论】:

  • 调用你的类Object 只会导致问题,不要将你的类命名为System 命名空间中已经存在的类型。事实上,这可能是您的问题的根本原因。
  • @ScottChamberlain 这只是为了学习如何序列化它在实际代码中不会像这样的东西,当我实现它时。

标签: c# xml dictionary serialization


【解决方案1】:

问题是您在反序列化期间丢失了代理List&lt;DictionaryEntry&gt; 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&lt;DictionaryEntry&gt; 代理属性在反序列化期间失败的解释,请参阅 Cannot deserialize XML into a list using XML Deserializer。如那里所述:

  1. XmlSerializer 调用 getter 来获取列表。如果为 null,它分配一个列表并通过 setter 设置它。它在读取时将列表保存在某个局部变量中。

  2. 它反序列化每个列表元素,并将其添加到它所持有的列表中。

  3. 就是这样。之后它永远不会调用包含类的 list 属性设置器。因此,列表的内容永远不会填充到您的字典中。

  4. 但是,由于数组一旦分配就无法调整大小,因此必须在读取和反序列化其内容后分配和设置它。因此,数组属性可以在反序列化期间充当代理项。

【讨论】:

  • 谢谢!将其更改为数组,现在它就像一个魅力!
猜你喜欢
  • 2015-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
相关资源
最近更新 更多