使用C#XmlSerializer对数组元素进行额外包装

使用C#XmlSerializer对数组元素进行额外包装,c#,arrays,xml,serialization,C#,Arrays,Xml,Serialization,我有以下课程: namespace XmlSerializerTest { using System; using System.Collections.Generic; using System.Xml.Serialization; [Serializable] [XmlRoot( Namespace = "My:NS" )] [XmlType( Namespace = "My:NS" )] [XmlInclude( typeof( C

我有以下课程:

namespace XmlSerializerTest
{
    using System;
    using System.Collections.Generic;
    using System.Xml.Serialization;

    [Serializable]
    [XmlRoot( Namespace = "My:NS" )]
    [XmlType( Namespace = "My:NS" )]
    [XmlInclude( typeof( Command ) )]
    [XmlInclude( typeof( ImSession ) )]
    public class CommandBase
    {
        [XmlAttribute]
        public string Version { get; set; }
    }

    [Serializable]
    [XmlType( Namespace = "My:NS" )]
    [XmlInclude( typeof( ImSession[ ] ) )]
    public class Command : CommandBase
    {
        [XmlArray]
        [XmlArrayItem( typeof( ImSession ) )]
        public object[ ] Content { get; set; }
    }

    [Serializable]
    [XmlType( Namespace = "My:NS" )]
    public class ImSession
    {
        [XmlElement]
        public string ClientId { get; set; }

        [XmlElement]
        public DateTime StartTime { get; set; }

        [XmlArray]
        public List<Matrix.Xmpp.Client.Message> Messages { get; set; }
    }
}
这将导致以下XML,同一序列化程序无法正确反序列化:

<?xml version="1.0" encoding="utf-8"?>
<CommandBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="Command" Version="TEST" xmlns="My:NS">

  <Content>
    <ImSession>
      <ClientId>Client A</ClientId>
      <StartTime>2015-08-11T00:00:00-04:00</StartTime>
      <Messages>
        <Message>
          <message to="a@b.com/c" xmlns="jabber:client">
            <body>TEST BODY A</body>
          </message>
        </Message>
        <Message>
          <message to="a@b.com/c" xmlns="jabber:client">
            <body>TEST BODY B</body>
          </message>
        </Message>
      </Messages>
    </ImSession>
    <ImSession>
      <ClientId>Client B</ClientId>
      <StartTime>2015-08-11T21:55:18.4624832-04:00</StartTime>
      <Messages>
        <Message>
          <message to="c@b.com/a" xmlns="jabber:client">
            <body>TEST BODY C</body>
          </message>
        </Message>
        <Message>
          <message to="c@b.com/a" xmlns="jabber:client">
            <body>TEST BODY D</body>
          </message>
        </Message>
      </Messages>
    </ImSession>
  </Content>
</CommandBase>

在调试器中检查
d
,可以发现它实际上是一个命令对象,其中包含ImSessions,每个消息的Messages数组中都有对象,它声称是Matrix.Xmpp.Client.Message,但除了子节点的私有集合外,所有属性都为null(与xml匹配),其中包含实际的消息对象,所有属性与预期一致。

嵌套似乎来自
矩阵.Xmpp.Client.Message
类本身。您是否尝试过序列化和反序列化该类的单个实例?似乎不是开源的,所以你能用一个简单的替换类重现这个问题吗?是的。(小写)元素来自矩阵。该类继承自XElement,并对其调用ToString将生成与上面xml中显示的完全相同的元素。我更感兴趣的是额外(大写m)元素来自何处,以及为什么运行时无法反序列化它序列化的内容,即使在同一应用程序中使用相同的XMLSerializer。它不应该是1对1吗?默认情况下,
XmlSerializer
将集合包装在容器元素中。如果你不想要这个,请参阅。然而,我不认为这是你问题的原因。当我试图用一个简单的POCO代替
Matrix.Xmpp.Client.Message
来重现您的问题时,我做不到(反序列化工作很好)。所以我认为
消息
有问题。但是,为了以防万一,请尝试一下这个答案。另外,你能用反序列化代码更新你的问题吗?您只显示序列化。已将反序列化程序代码添加到文章底部。我不担心Messages包装器元素。我希望在整个集合中有一个包装器元素,但在集合中的每个项目周围没有额外的包装器。即使是这样,是否有方法覆盖该行为并将每个元素的序列化留给该对象本身?嵌套似乎来自
Matrix.Xmpp.Client.Message
类本身。您是否尝试过序列化和反序列化该类的单个实例?似乎不是开源的,所以你能用一个简单的替换类重现这个问题吗?是的。(小写)元素来自矩阵。该类继承自XElement,并对其调用ToString将生成与上面xml中显示的完全相同的元素。我更感兴趣的是额外(大写m)元素来自何处,以及为什么运行时无法反序列化它序列化的内容,即使在同一应用程序中使用相同的XMLSerializer。它不应该是1对1吗?默认情况下,
XmlSerializer
将集合包装在容器元素中。如果你不想要这个,请参阅。然而,我不认为这是你问题的原因。当我试图用一个简单的POCO代替
Matrix.Xmpp.Client.Message
来重现您的问题时,我做不到(反序列化工作很好)。所以我认为
消息
有问题。但是,为了以防万一,请尝试一下这个答案。另外,你能用反序列化代码更新你的问题吗?您只显示序列化。已将反序列化程序代码添加到文章底部。我不担心Messages包装器元素。我希望在整个集合中有一个包装器元素,但在集合中的每个项目周围没有额外的包装器。即使是这样,是否有方法覆盖该行为并将每个元素的序列化留给该对象本身?
<?xml version="1.0" encoding="utf-8"?>
<CommandBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="Command" Version="TEST" xmlns="My:NS">

  <Content>
    <ImSession>
      <ClientId>Client A</ClientId>
      <StartTime>2015-08-11T00:00:00-04:00</StartTime>
      <Messages>
        <Message>
          <message to="a@b.com/c" xmlns="jabber:client">
            <body>TEST BODY A</body>
          </message>
        </Message>
        <Message>
          <message to="a@b.com/c" xmlns="jabber:client">
            <body>TEST BODY B</body>
          </message>
        </Message>
      </Messages>
    </ImSession>
    <ImSession>
      <ClientId>Client B</ClientId>
      <StartTime>2015-08-11T21:55:18.4624832-04:00</StartTime>
      <Messages>
        <Message>
          <message to="c@b.com/a" xmlns="jabber:client">
            <body>TEST BODY C</body>
          </message>
        </Message>
        <Message>
          <message to="c@b.com/a" xmlns="jabber:client">
            <body>TEST BODY D</body>
          </message>
        </Message>
      </Messages>
    </ImSession>
  </Content>
</CommandBase>
<?xml version="1.0" encoding="utf-8"?>
<CommandBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="Command" Version="TEST" xmlns="My:NS">

  <Content>
    <ImSession>
      <ClientId>Client A</ClientId>
      <StartTime>2015-08-11T00:00:00-04:00</StartTime>
      <Messages>
        <message to="a@b.com/c" xmlns="jabber:client">
          <body>TEST BODY A</body>
        </message>
        <message to="a@b.com/c" xmlns="jabber:client">
          <body>TEST BODY B</body>
        </message>
      </Messages>
    </ImSession>
    <ImSession>
      <ClientId>Client B</ClientId>
      <StartTime>2015-08-11T21:55:18.4624832-04:00</StartTime>
      <Messages>
        <message to="c@b.com/a" xmlns="jabber:client">
          <body>TEST BODY C</body>
        </message>
        <message to="c@b.com/a" xmlns="jabber:client">
          <body>TEST BODY D</body>
        </message>
      </Messages>
    </ImSession>
  </Content>
</CommandBase>
StringBuilder sb = new StringBuilder( );
ser.Serialize( new StringWriter( sb ), c );
object d = ser.Deserialize( new StringReader( sb.ToString( ) ) );