Je voudrais implémenter ISerializable pour une classe C# qui contient une liste d'enfants typés similaires. Prenons l'exemple suivant:ISerializable avec les enfants récursifs
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace serialisation
{
[Serializable]
internal class Nested : ISerializable
{
public string Name { get; set; }
public List<Nested> Children { get; set; }
public Nested(string name)
{
Name = name;
Children = new List<Nested>();
}
protected Nested(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
Name = info.GetString("Name");
// This doesn't work:
Nested[] children = (Nested[])info.GetValue("Children", typeof(Nested[]));
Children = new List<Nested>(children);
// This works:
// Children = (List<Nested>)info.GetValue("Children", typeof(List<Nested>));
}
public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
info.AddValue("Name", Name);
// This doesn't work:
info.AddValue("Children", Children.ToArray());
// This works:
//info.AddValue("Children", Children);
}
}
internal class Program
{
private static void Main(string[] args)
{
// Generate a hierarchy
Nested root = new Nested("root");
Nested child1 = new Nested("child1");
Nested child2 = new Nested("child2");
Nested child3 = new Nested("child3");
child1.Children.Add(child2);
child1.Children.Add(child3);
root.Children.Add(child1);
Nested deserialized;
BinaryFormatter binaryFmt = new BinaryFormatter();
// Serialize
using (var fs = new FileStream("Nested.xml", FileMode.OpenOrCreate))
{
binaryFmt.Serialize(fs, root);
}
// Deserialize
using (var fs = new FileStream("Nested.xml", FileMode.OpenOrCreate))
{
deserialized = (Nested)binaryFmt.Deserialize(fs);
}
// deserialized.Children contains one null child
Console.WriteLine("Original Name: {0}", root.Name);
Console.WriteLine("New Name: {0}", deserialized.Name);
}
}
}
Dans l'exemple ci-dessus, Nested.GetObjectData et le constructeur de sérialiseur pour emboîtés sont invoquées 4 fois, l'un après l'autre.
L'ajout des enfants au sérialiseur en tant que tableau imbriqué renvoie un tableau correctement dimensionné lors de la désérialisation, mais tous les éléments seront null. Cependant, changer le type de tableau imbriqué en liste imbriquée corrigera magiquement les éléments nuls après l'appel des constructeurs pour les enfants.
Ce que je voudrais savoir est:
- Quelle est la particularité Nested Liste?
- Quelle est la méthode recommandée pour sérialiser une classe avec une structure récursive comme celle-ci?
Mise à jour:
Il semble qu'il y ait une interface supplémentaire, IDeserializationCallback.OnDeserialization, qui est appelée après désérialisation a eu lieu (l'ordre d'appel est non-déterministe). Vous pouvez stocker le tableau désérialisé dans une variable de membre temp dans le constructeur, puis l'affecter à une liste dans cette méthode. À moins que je ne manque quelque chose, cela semble moins qu'idéale car vous devez encombrer votre implémentation avec des vars temp.
Je crois que c'est une question similaire qui a été répondu: http://stackoverflow.com/questions/4339602/désérialisation-d'un tableau-toujours-donne-un-tableau-de-null –
J'ai aussi trouvé la même question il y a quelques minutes. Je ne devais pas être assez spécifique avec mes termes de recherche précédents ... – ChocolatePocket