2013-06-22 3 views
3

Как видно из названия говорит, когда я десериализации следующий файл я только получить первый (и всегда первый) элемент:Массив десериализации возвращает только один элемент

<?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; } 
} 

Там нет exceptio n происходит.

Edit: Проблема возникает, когда я включаю мой класс, который делает пользовательские 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 десериализатор, который работает весь список останавливается и не читает никаких дополнительных элементов.

ответ

1

Я не вижу никаких проблем. Я даже воспроизвел ваш сценарий (полный тест, приведенный ниже) вашего кода, и он выполняет свою работу правильно.

Попробуйте найти в другом месте (например, убедитесь, что пройденный xml - это тот, который вы ожидаете). Но сериализации работает правильно с отображением # класса C

EDIT: класс 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); 
    } 
} 
+0

Вы правы, это не о десериализации как таковой, а под им используя неуправляемый класс (AuthHash), и это, по-видимому, вызывает проблему. Если я удалю AuthHash из xml, он будет считывать все элементы. – Muepe

+0

Я показал, как вы можете сделать преобразование из base64 в байт [] и обратно ..., который должен решить все ваши проблемы. –

+0

Спасибо за это, но в моем случае AuthHash - это класс C++/CLI, который обертывает неуправляемый объект. Таким образом, он нуждается в специальной «обработке» при сериализации/десериализации. – Muepe

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; } 
    } 
} 
+0

Я действительно нашел проблему быть моей десериализацией BigNumber AuthHash. Очевидно, он переходит к следующему элементу и, таким образом, он только считывает один из них. Однако xml-сериализатор работает нормально. – Muepe

+0

Deserialization элемента AuthHash отлично работает с указанным выше, если вы попробуете (измените строку в каждом из двух элементов AuthHash, чтобы сделать ее проще). Я полагаю, вы могли бы попытаться использовать управляемый класс для чтения и затем сопоставить неуправляемый класс, так как я не знаю последствий использования неуправляемого класса в этом примере.Это делает отображение определенного типа немного грязным, хотя –

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 гарантирует, что он продвинется к следующему узлу. Поскольку я не делал этого, у десериализатора выше была проблема, но вместо того, чтобы бросать исключение, он просто прекращает разбор и возвращает то, что получил до сих пор ...