2013-06-22 3 views
3

Comme le dit le titre quand je désérialiser le fichier suivant je ne reçois que le premier (et toujours le premier) élément:Tableau désérialisation seulement retour 1 élément

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

Mon code à deserialize:

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

et list.Count est alors 1. ServerConnections ressemble que:

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

Il n'y a pas exceptio n passe.

Edit: Le problème se produit lorsque j'inclus ma classe qui fait sérialisation XML personnalisé (implémente IXmlSerializable). Ce qu'il fait est le suivant:

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()); 
} 

Bien que les données contient les données correctes après ReadXml désérialiseur qui fonctionne toute la liste des arrêts et ne lit pas d'éléments supplémentaires.

Répondre

1

Je ne vois aucun problème. J'ai même reproduit votre scénario (test complet ci-joint) de votre code, et il fait son travail correctement. Essayez d'effectuer une recherche ailleurs (par exemple, assurez-vous que le résultat xml est celui que vous attendez). Mais sérialisation fonctionne correctement avec votre C# mapping de classe

EDIT: AuthHash pas de classe ne la conversion pour vous de byte[] à base64 et retour

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

Vous avez raison, ce n'est pas une question de désérialisation en soi mais en dessous en utilisant une classe non gérée (l'AuthHash) et cela semble causer un problème. Si je supprime l'AuthHash du xml, il lit tous les éléments. – Muepe

+0

J'ai montré comment vous pouvez faire la conversion de base64 à octet [] et retour ... qui devrait résoudre tous vos problèmes –

+0

Merci pour cela, mais dans mon cas, l'AuthHash est une classe C++/CLI qui encapsule un non géré objet. Il a donc besoin d'un "traitement" spécial lorsqu'il est sérialisé/désérialisé. – Muepe

1

Même ici, cela semble fonctionner très bien pour moi en utilisant un code similaire a la votre.

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

J'ai effectivement trouvé le problème d'être ma désérialisation de l'AuthHash BigNumber. Il saute évidemment à l'élément suivant et ainsi il ne lit que l'un d'entre eux. Le sérialiseur xml semble fonctionner correctement cependant. – Muepe

+0

La désérialisation de l'élément AuthHash fonctionne bien avec ce qui précède si vous l'essayez (change la chaîne dans chacun des deux éléments AuthHash pour le rendre plus facile). Je suppose que vous pourriez essayer d'utiliser une classe managée pour la lecture, puis mapper à la classe non managée, car je ne connais pas les ramifications de l'utilisation de la classe non managée dans cet exemple.Cela rend le mappage au type défini un peu sale –

0

Bien fizzlesticks, le problème était que j'ai oublié une toute petite ligne dans la désérialisation. Il devrait être comme ça:

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(); 
} 

Le ReadEndElement s'assure qu'il avance au noeud suivant. Comme je ne l'ai pas fait, le désérialiseur ci-dessus a eu un problème mais au lieu de lancer une exception il s'arrête juste d'analyser et retourne ce qu'il a obtenu jusqu'à présent ...

Questions connexes