【问题标题】:Deserialize list of objects with list使用列表反序列化对象列表
【发布时间】:2014-03-25 11:21:34
【问题描述】:

我有以下 XML:

<?xml version="1.0" encoding="utf-8"?>
<CallEvents xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <CallEvent>
    <Time>2014-02-24T06:44:27.12</Time>
    <Type>Inner</Type>
    <Fs>
      <StrPair>
        <Key>Name</Key>
        <Value>Call1</Value>
      </StrPair>
      <StrPair>
        <Key>Owner</Key>
        <Value>Ali</Value>
      </StrPair>
    </Fs>
  </CallEvent>
  <CallEvent>
    <Time>2014-02-24T06:44:29.089</Time>
    <Type>Outer</Type>
    <Fs>
      <StrPair>
        <Key>Name</Key>
        <Value>Call2</Value>
      </StrPair>
      <StrPair>
        <Key>Id</Key>
        <Value>3242</Value>
      </StrPair>
      <StrPair>
        <Key>Another</Key>
        <Value>123</Value>
      </StrPair>
    </Fs>
  </CallEvent>
</CallEvents>

我试图反序列化它,但它不想反序列化列表Fs。我得到CallEventsCallEvent 项目,CallEvent 的成员除了列表Fs 之外填充了正确的值。列表Fs 为空。为什么? 我做错了什么?

class Program
{
    static void Main(string[] args)
    {
        string xmlFile = "call_events.xml";
        CallEvents events = CallEvents.OpenFromXmlFile(xmlFile);
        Console.ReadKey();
    }
}

[Serializable]
public class CallEvent
{
    [XmlElement]
    public DateTime Time;
    [XmlElement]
    public CallEventType Type;

    public CallEvent()
    {
        this.Fields = new Dictionary<string, string>();
    }

    [XmlArray("Fs"), XmlArrayItem("StrPair")]
    public List<StrPair> Fs
    {
        get
        {
            var list = new List<StrPair>();
            foreach (var pair in Fields)
            {
                list.Add(new StrPair(pair.Key, pair.Value));
            }
            return list;
        }
        set
        {
            Fields.Clear();
            foreach (var dictPair in value)
            {
                Fields.Add(dictPair.Key, dictPair.Value);
            }
        }
    }

    [XmlIgnore]
    public Dictionary<string, string> Fields;

    public void ParseFields(List<LogMessage> eventLogMessages)
    {
        int eventLogMessagesCount = eventLogMessages.Count;
        this.Fields.Clear();
        for (int i = 0; i < eventLogMessagesCount; i++)
        {
            LogMessage logMessage = eventLogMessages[i];
            int pos = logMessage.Message.IndexOf(": ");
            if(pos == -1)
                continue;
            string fieldName = logMessage.Message.Substring(0, pos);
            pos+=2;
            string fieldValue = logMessage.Message.Substring(pos);
            if (this.Fields.ContainsKey(fieldName))
            {
                this.Fields[fieldName] += ("\r\n" + fieldValue);
            }
            else
            {
                this.Fields.Add(fieldName, fieldValue);
            }
        }
    }

    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendFormat("{0} {1} | ", Type, Time);
        foreach (var pair in Fields)
        {
            sb.AppendFormat("{0}: {1}, ", pair.Key, pair.Value);
        }
        return sb.ToString();
    }

    [Serializable]
    public class StrPair
    {
        [XmlElement]
        public string Key;
        [XmlElement]
        public string Value;

        public StrPair() { }

        public StrPair(string key, string value)
        {
            Key = key;
            Value = value;
        }
    }
}

[XmlRoot("CallEvents")]
public class CallEvents : List<CallEvent>
{
    static public CallEvents OpenFromXmlFile(string xmlFileName)
    {
        CallEvents callEvents;// = new CallEvents();
        XmlSerializer ser = new XmlSerializer(typeof(CallEvents));
        XmlReader xmlReader = new XmlTextReader(xmlFileName);
        try
        {
            callEvents = (CallEvents)ser.Deserialize(xmlReader);
        }
        finally
        {
            xmlReader.Close();
        }
        return callEvents;
    }

    public void SaveToXmlFile(string xmlFileName)
    {
        XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
        xmlWriterSettings.Encoding = System.Text.Encoding.UTF8;
        xmlWriterSettings.Indent = true;

        XmlSerializer ser = new XmlSerializer(this.GetType());
        XmlWriter xmlWriter = null;
    tryAgain:
        try
        {
            xmlWriter = XmlTextWriter.Create(xmlFileName, xmlWriterSettings);
            ser.Serialize(xmlWriter, this);
        }
        catch (Exception ex)
        {
            System.Windows.Forms.DialogResult dr = System.Windows.Forms.MessageBox.Show("Couldn't serialize to XML. Details: " + ex.Message, "Error", System.Windows.Forms.MessageBoxButtons.RetryCancel, System.Windows.Forms.MessageBoxIcon.Warning);
            if (dr == System.Windows.Forms.DialogResult.Retry)
            {
                goto tryAgain;
            }
        }
        finally
        {
            if (xmlWriter != null)
            {
                xmlWriter.Close();
            }
        }
    }
}

【问题讨论】:

  • “我做错了什么?” - 你忽略了异常。
  • @CodeCaster 什么异常?它毫无例外地运行。
  • 如果你没有真正告诉我们问题,我们怎么能告诉你做错了?
  • 如果您删除了 Fs 属性的自定义 get/set 实现,它会起作用吗?
  • @AnatoliiGumennyi 如果您需要控制反序列化(以填充您的字典),那么您可以让您的 CallEvent 类实现 IXmlSerializable 并覆盖 ReadXml 方法。

标签: c# xml list xml-deserialization


【解决方案1】:

我已经用了一段时间了,所以代码可能需要一些修饰。

CallEvents events;

using(XmlReader reader = XmlReader.Create("call_events.xml"))
{
    XmlDeserializer deSerializer = new XmlDeserializer(typeof(CallEvents));
    events = (CallEvents)deSerializer.Deserialize(reader);
}

【讨论】:

    猜你喜欢
    • 2014-12-10
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-12
    • 2020-10-31
    • 2020-11-06
    • 1970-01-01
    相关资源
    最近更新 更多