2010-01-04 6 views
1

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!

+0

ScriptListEntry est-il sérialisable? Avez-vous essayé de sérialiser une seule instance? –

+0

Avez-vous essayé de trouver des différences dans ce qui est passé dans 'deepCopy'? –

+0

J'avais manqué de faire 'ScriptListEntry' sérialisable - voir ci-dessous. Merci pour vos commentaires! – jokki

Répondre

2

Vous avez coupé le texte du message d'erreur - PublicKeyToken=null est la fin du nom qualifié d'assembly d'un type - il devrait ressembler à quelque chose comme Foo.Bar, Baz, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null - qui est, classe Foo.Bar dans l'assemblage Baz de la version 1.2.3.4, neutre culture , pas signé. Dans votre cas, l'erreur est que ce type n'est pas attribué [Serializable].

+0

Je vois, donc le "PublicKeyToken = null" ne signifie pas que j'ai passé 'null' à la fonction, cela a du sens! Et vous avez raison, j'avais omis de donner à 'ScriptListEntry' l'attribut [Serializable]. Cela fonctionne maintenant, merci beaucoup! – jokki

Questions connexes