数组反序列化只返回1个元素

时间:2013-06-22 10:14:16

标签: c# .net xml

正如标题所说,当我反序列化以下文件时,我只获得第一个(并且始终是第一个)元素:

<?xml version="1.0"?>
<ServerConnections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Entries>
    <ServerConnectionEntry>
      <Name>Local</Name>
      <Host>127.0.0.1</Host>
      <Port>15556</Port>
      <Username>TestUser</Username>
      <AuthHash>
        <base64Binary>u7a0NN4uOvCrb5t5UWVVEl14Ygo=</base64Binary>
      </AuthHash>
    </ServerConnectionEntry>
    <ServerConnectionEntry>
      <Name>Local2</Name>
      <Host>127.0.0.1</Host>
      <Port>15556</Port>
      <Username>TestUser</Username>
      <AuthHash>
        <base64Binary>u7a0NN4uOvCrb5t5UWVVEl14Ygo=</base64Binary>
      </AuthHash>
    </ServerConnectionEntry>
  </Entries>
</ServerConnections>

我的反序列化代码:

var list = (ServerConnections)mSerializer.Deserialize(inputStream)).Entries;
然后

和list.Count为1. ServerConnections看起来像这样:

public class ServerConnections
{
    public ServerConnectionEntry[] Entries { get; set; }
}

没有例外。

修改 当我包含我的自定义xml序列化的类(实现IXmlSerializable)时,会出现问题。它的作用如下:

void BigNumber::ReadXml(System::Xml::XmlReader^ reader) {
    reader->ReadStartElement();
    XmlSerializer^ serializer = gcnew XmlSerializer(cli::array<Byte>::typeid);
    cli::array<Byte>^ data = (cli::array<Byte>^)serializer->Deserialize(reader);
    pin_ptr<unsigned char> ptr(&data[0]);
    BN_bin2bn(ptr, data->Length, mNumber);
}

void BigNumber::WriteXml(System::Xml::XmlWriter^ writer) {
    XmlSerializer^ serializer = gcnew XmlSerializer(cli::array<Byte>::typeid);
    serializer->Serialize(writer, ToByteArray());
}

虽然数据在ReadXml之后包含正确的数据,但整个列表的解串器会停止并且不会读取任何其他元素。

3 个答案:

答案 0 :(得分:1)

我没有看到任何问题。我甚至已经复制了你的代码的(下面的完整测试),它正在正确地完成它的工作。

尝试在其他地方搜索(例如,确保传递的xml是您期望的那个)。但序列化与您的C#类映射

正常工作

编辑:AuthHash类没有为您从byte[]转换为base64并返回

public class ServerConnections
{
    public ServerConnectionEntry[] Entries { get; set; }
}
public class ServerConnectionEntry
{
    public string Name { get; set; }
    public AuthHash AuthHash { get; set; }
}
public class AuthHash
{
    [XmlIgnore]
    public byte[] Hash { get; set; }
    public string base64Binary
    {
        get { return Convert.ToBase64String(Hash); }
        set { Hash = Convert.FromBase64String(value); }
    }
}
[TestClass]
public class DeserializationTest
{
    public const string MyXml = @"<?xml version=""1.0""?>
<ServerConnections 
   xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" 
   xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
  <Entries>
    <ServerConnectionEntry>
      <Name>Local</Name>
      <Host>127.0.0.1</Host>
      <Port>15556</Port>
      <Username>TestUser</Username>
      <AuthHash>
        <base64Binary>u7a0NN4uOvCrb5t5UWVVEl14Ygo=</base64Binary>
      </AuthHash>
    </ServerConnectionEntry>
    <ServerConnectionEntry>
      <Name>Local2</Name>
      <Host>127.0.0.1</Host>
      <Port>15556</Port>
      <Username>TestUser</Username>
      <AuthHash>
        <base64Binary>u7a0NN4uOvCrb5t5UWVVEl14Ygo=</base64Binary>
      </AuthHash>
    </ServerConnectionEntry>
  </Entries>
</ServerConnections>
";
    [TestMethod]
    public void Deserialization_Has_Two_Elements()
    {
        TextReader reader = new StringReader(MyXml);
        var mySerializer = new XmlSerializer(typeof(ServerConnections));

        var list = ((ServerConnections)mySerializer.Deserialize(reader)).Entries;

        Assert.IsTrue(list.Count() == 2);

        Assert.IsTrue(list.First().Name == "Local");
        Assert.IsTrue(list.Last().Name == "Local2");

        Assert.IsTrue(list.First().AuthHash.Hash.Length > 0);
        Assert.IsTrue(list.Last().AuthHash.Hash.Length > 0);
    }
}

答案 1 :(得分:1)

同样,这似乎对我使用类似于你的代码很好。

 public class Program
{
    static void Main(string[] args)
    {
        XmlSerializer deserializer = new XmlSerializer(typeof(ServerConnections));
        var reader = new StreamReader(@"../../Test.xml");
        var entries = (ServerConnections)deserializer.Deserialize(reader);
        reader.Close();
    }

    public class ServerConnections
    {
        public ServerConnectionEntry[] Entries { get; set; }
    }

    public class ServerConnectionEntry
    {
        public string Name { get; set; }
        public string Host { get; set; }
        public string Port { get; set; }
        public string Username { get; set; }
        public BinaryCode AuthHash { get; set; }
    }

    public class BinaryCode
    {
        [XmlElement("base64Binary")]
        public string Code { get; set; }
    }
}

答案 2 :(得分:0)

好极了,问题是我在反序列化中忘了一条小小的线。它应该是这样的:

void BigNumber::ReadXml(System::Xml::XmlReader^ reader) {
    reader->ReadStartElement();
    XmlSerializer^ serializer = gcnew XmlSerializer(cli::array<Byte>::typeid);
    cli::array<Byte>^ data = (cli::array<Byte>^)serializer->Deserialize(reader);
    pin_ptr<unsigned char> ptr(&data[0]);
    BN_bin2bn(ptr, data->Length, mNumber);
    reader->ReadEndElement();
}

ReadEndElement确保它前进到下一个节点。由于我没有这样做,上面的反序列化器有一个问题,但不是抛出异常,它只是停止解析并返回它到目前为止所得到的...