J'ai des difficultés à copier en profondeur une liste.Problème lors de la copie en profondeur d'une 'Liste <T>' C#
Ma fenêtre principale, appelée Form1
, a une instance de System.Collections.Generic.List<T>
et je souhaite donner la possibilité de modifier cette liste à travers une SettingsForm
séparée qui a une OK- et un bouton Annuler. Si l'utilisateur appuie sur "OK" alors les changements à la liste prendront effet mais si l'utilisateur appuie sur "Annuler" alors (naturellement) tous les changements doivent être rejetés. Pour réaliser cela, SettingsForm
est destiné à faire une copie complète de la liste, apporter les modifications demandées par l'utilisateur à la liste copiée, puis - si l'utilisateur appuie sur "OK - remettre la copie éditée à Form1
pour remplacer l'original
Pour faire la copie en profondeur, je me sers du MemoryStream
- solution BinaryFormatter
a suggéré here et mon problème est que lorsque j'appelle SettingsForm
une deuxième fois que je reçois une exception de ma fonction de copie en profondeur indiquant que null
n'est pas sérialisable Il est aussi. si j'avais passé null
à la fonction de copie en profondeur mais j'ai pris soin de ne pas le faire
Eh bien, si vous avez lu jusqu'ici, je suppose que vous aimeriez voir du code, alors nous y allons; d'abord les parties pertinentes de Form1
:
public partial class Form1 : Form
{
...
private List<ScriptListEntry> scriptList;
...
public Form1()
{
InitializeComponent();
...
// Create an empty script list
scriptList = new List<ScriptListEntry>();
...
}
...
private void toolStripButton2_Click(object sender, EventArgs e)
{
/* Will display 'SettingsForm' to allow the user to change the program
* settings.
*/
...
SettingsForm sform = new SettingsForm();
...
sform.setScriptList(scriptList);
sform.ShowDialog();
}
Puis SettingsForm
public partial class SettingsForm : Form
{
...
private List<ScriptListEntry> scriptList;
private List<ScriptListEntry> scriptListWorkingCopy;
public SettingsForm()
{
InitializeComponent();
scriptList = null;
scriptListWorkingCopy = null;
...
}
public void setScriptList(List<ScriptListEntry> scriptList_)
{
// Keep a reference to the original list
scriptList = scriptList_;
if (null != scriptList_)
{
if (0 != scriptList_.Count)
{
/* Make a working copy because settings made in 'SettingsForm' must
* not be committed until OK-button is clicked. 'DeepCopy' does not
* work if object to be copied is 'null' or the list is empty.
*/
scriptListWorkingCopy = DeepCopy<List<ScriptListEntry>>.deepCopy(scriptList_);
...
}
}
else
...
}
...
// OK-button
private void button1_Click(object sender, EventArgs e)
{
...
// Update the script list
if (null != scriptList)
{
scriptList.Clear();
scriptList.AddRange(scriptListWorkingCopy);
}
else
...
}
Et enfin la copie en profondeur à la machine, la ligne 11 ci-dessous jette l'exception
public static class DeepCopy<T>
{
/* Used for deep copying anything.
* Class 'T' must have [SerializableAttribute]
*/
public static T deepCopy(object objectToCopy)
{
using (MemoryStream memoryStream = new MemoryStream())
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, objectToCopy); // << Exception thrower
memoryStream.Seek(0, SeekOrigin.Begin);
return (T)binaryFormatter.Deserialize(memoryStream);
}
}
}
Créer la liste pour la première fois fonctionne très bien (j'ai vérifié son contenu) mais quand j'essaye d'afficher 'SettingsForm' une deuxième fois l'exception se produit. L'exception est 'System.Runtime.Serialization.SerializationException' - "PublicKeyToken = null 'n'est pas marqué comme sérialisable"
Merci d'avoir lu!
ScriptListEntry est-il sérialisable? Avez-vous essayé de sérialiser une seule instance? –
Avez-vous essayé de trouver des différences dans ce qui est passé dans 'deepCopy'? –
J'avais manqué de faire 'ScriptListEntry' sérialisable - voir ci-dessous. Merci pour vos commentaires! – jokki