2013-10-09 7 views
0

Je crée une liste, l'enregistre en XML (avec XmlSerializer) mais je ne réussis pas (bien que toutes les recherches sur le web ...) à désérialiser.XML - Ne peut pas désérialiser après sérialiser

Mes entités sont:

public class basicTxtFile 
{ 
    public string filename; 
    public string description; 
} 

public class fileTools 
{ 
}; 

public class textboxTool : fileTools // text box 
{ 
    public string defaultText; 
    public bool multiLine; 
    public bool browseButton; 
}; 

public class comboboxTool : fileTools // combo box 
{ 
    public List<string> values = new List<string>(); 
}; 

// Must file, can choose tools: textbox and\or combobox 
public class mustFiles : basicTxtFile 
{ 
    public List<fileTools> mustTools = new List<fileTools>(); 
}; 

public class OptionalFiles : mustFiles 
{ 
    public bool exist; // checkbox for defualt value - if the file is exist, if not. 
}; 

Dans mon application, je cageot une liste et je le remplir manuellement. Après je l'ai enregistré avec ce code:

// Save list into XML - success 
XmlSerializer serializer = new XmlSerializer(typeof(List<mustFiles>), new Type[] {typeof(fileTools), typeof(textboxTool), typeof(comboboxTool)}); 

using (FileStream stream = File.OpenWrite("MustFiles.xml")) 
{ 
    serializer.Serialize(stream, mustTxtFiles); 
} 

Ensuite, j'essaie de charger le fichier XML dans la liste, mais il a échoué en raison de: « Il y a une erreur dans le document XML (2, 2). » et _ innerException = "n'était pas prévu." bien que le fichier xml génère automatiquement.

Mon code de charge est:

// Load XML file into list 
List<mustFiles> mustTry = new List<mustFiles>(); 
mustTry = bl.loadXmlIntoList<mustFiles>("MustFiles.xml", "mustFiles"); 

fonction loadXmlIntoList:

public List<T> loadXmlIntoList<T>(string xmlFileName, string xmlElemnetName) 
{ 
    XmlRootAttribute xRoot = new XmlRootAttribute(); 
    xRoot.ElementName = xmlElemnetName; 
    xRoot.IsNullable = true; 

    XmlSerializer serializer = new XmlSerializer(typeof(T), xRoot); 

    using (FileStream stream = File.OpenRead(xmlFileName)) 
    { 
     List<T> dezerializedList = (List<T>)serializer.Deserialize(stream); 
     return dezerializedList; 
    } 
} 

Ma question: Ce que je fait de mal? comment puis-je charger le fichier xml dans la liste?

Merci!

Le fichier XML (qui génèrent automatiquement) ressemble à ceci:

<?xml version="1.0"?> 
<ArrayOfMustFiles xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <mustFiles> 
    <filename>file1.txt</filename> 
    <description>desc1</description> 
    <mustTools> 
     <fileTools xsi:type="textboxTool"> 
     <defaultText>Default text 01</defaultText> 
     <multiLine>false</multiLine> 
     <browseButton>false</browseButton> 
     </fileTools> 
    </mustTools> 
    </mustFiles> 
    <mustFiles> 
    <filename>file2.txt</filename> 
    <description>desc2</description> 
    <mustTools> 
     <fileTools xsi:type="textboxTool"> 
     <defaultText>Defualt text 02</defaultText> 
     <multiLine>true</multiLine> 
     <browseButton>true</browseButton> 
     </fileTools> 
     <fileTools xsi:type="comboboxTool"> 
     <values> 
      <string>Val1</string> 
      <string>Val2</string> 
      <string>Val3</string> 
     </values> 
     </fileTools> 
    </mustTools> 
    </mustFiles> 
    <mustFiles> 
    <filename>file2.txt</filename> 
    <description>desc2</description> 
    <mustTools> 
     <fileTools xsi:type="textboxTool"> 
     <defaultText>Defualt text 03</defaultText> 
     <multiLine>false</multiLine> 
     <browseButton>true</browseButton> 
     </fileTools> 
     <fileTools xsi:type="comboboxTool"> 
     <values> 
      <string>ComboVal 1</string> 
      <string>ComboVal 2</string> 
      <string>ComboVal 3</string> 
     </values> 
     </fileTools> 
     <fileTools xsi:type="comboboxTool"> 
     <values> 
      <string>Second ComboVal 1</string> 
      <string>Second ComboVal 2</string> 
      <string>Second ComboVal 3</string> 
     </values> 
     </fileTools> 
     <fileTools xsi:type="textboxTool"> 
     <defaultText>Second defualt text 03</defaultText> 
     <multiLine>true</multiLine> 
     <browseButton>false</browseButton> 
     </fileTools> 
    </mustTools> 
    </mustFiles> 
</ArrayOfMustFiles> 

Mise à jour: J'essaie aussi d'ajouter {get; set;} aux entités, comme ceci:

public class basicTxtFile 
{ 
    public string filename{ set; get; } 
    public string description{ set; get; } 
} 

public class fileTools 
{ }; 

public class textboxTool : fileTools 
{ 
    public string defaultText{ set; get; } 
    public bool multiLine{ set; get; } 
    public bool browseButton{ set; get; } 
}; 

public class comboboxTool : fileTools 
{ 
    public List<string> values { set; get; } 
    public comboboxTool() 
    { 
     values = new List<string>(); 
    } 
}; 

public class mustFiles : basicTxtFile 
{ 
    public List<fileTools> mustTools { set; get; } 
    public mustFiles() 
    { 
     mustTools = new List<fileTools>(); 
    } 
}; 
+0

Je ne vois pas un appel à deserialize(). Qu'est-ce que loadXmlIntoList()? –

+0

désolé, j'ai oublié de le changer. Je vais mettre à jour ma question maintenant. Merci – AsfK

+0

Ajouter la fonction. merci encore – AsfK

Répondre

1

Je ne suis pas un expert XML. Qu'essayez-vous de faire avec XmlRootAttribute dans loadXmlIntoList()?

Je l'ai retravaillé un peu afin que le code de désérialisation ressemble plus à son homologue de sérialisation:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     List<mustFiles> mustTxtFiles = new List<mustFiles>(); 

     mustFiles mf = new mustFiles(); 
     mf.filename = "filenameA"; 
     mf.description = "descriptionA"; 
     textboxTool tbt = new textboxTool(); 
     tbt.defaultText = "defaultTextA"; 
     tbt.browseButton = true; 
     tbt.multiLine = true; 
     mf.mustTools.Add(tbt); 
     mustTxtFiles.Add(mf); 

     mf = new mustFiles(); 
     mf.filename = "filenameB"; 
     mf.description = "descriptionB"; 
     tbt = new textboxTool(); 
     tbt.defaultText = "defaultTextB"; 
     tbt.browseButton = true; 
     tbt.multiLine = true; 
     mf.mustTools.Add(tbt); 
     mustTxtFiles.Add(mf); 

     // serialize it 
     XmlSerializer serializer = new XmlSerializer(typeof(List<mustFiles>), new Type[] {typeof(fileTools), typeof(textboxTool), typeof(comboboxTool)}); 
     string xmlFile = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MustFiles.xml"); 
     using (System.IO.FileStream stream = File.OpenWrite(xmlFile)) 
     { 
      serializer.Serialize(stream, mustTxtFiles); 
     } 

     // Why not just this? 
     // deserialize it 
     //List<mustFiles> mustTry; 
     //using (FileStream stream = File.OpenRead(xmlFile)) 
     //{ 
     // mustTry = (List<mustFiles>)serializer.Deserialize(stream); 
     //} 

     // deserialize it with generic function: 
     List<mustFiles> mustTry = loadXml<List<mustFiles>>(xmlFile, new Type[] { typeof(fileTools), typeof(textboxTool), typeof(comboboxTool) }); 
    } 

    public T loadXml<T>(string xmlFileName, Type[] additionalTypes) 
    { 
     XmlSerializer serializer = new XmlSerializer(typeof(T), additionalTypes); 
     using (FileStream stream = File.OpenRead(xmlFileName)) 
     { 
      return (T)serializer.Deserialize(stream); 
     } 
    } 

} 
+0

Vraiment merci !!! J'ai passé des heures là-dessus, vraiment merci !! – AsfK

0

Je pense que votre est- causée par l'absence des méthodes get {} set {} des propriétés que vous êtes en train de sérialiser ou de désérialiser!

Vous devez l'utiliser en tant que propriétés si vous souhaitez les utiliser en sérialisation. il y a des problèmes si vous les utilisez uniquement comme champs sans obtenir &

+0

J'ajoute '{get; set;} 'mais ça ne marche toujours pas. Pouvez-vous expliquer s'il vous plaît ce que vous voulez dire dans 'l'utiliser comme propriétés'. Merci. – AsfK

+0

Dans votre code, vous avez écrit public class basicTxtFile { public nom de fichier de la chaîne; description de chaîne publique; } les variables dans ce contexte sont des champs utilisables en tant que propriétés non encapsulées si vous utilisez à la place: public class basicTxtFile { nom public string {get; ensemble; } description de chaîne publique {get; ensemble; } } Cela fait des champs des propriétés en capsule! normalement, il devrait fonctionner avec le sérialiseur maintenant –

+0

vous devez ajouter get; ensemble; à ALLE pour les éléments XML éléments utilisés –

Questions connexes