Lorsque vous utilisez ce code pour sérialiser un objet:
public object Clone() { var serializer = new DataContractSerializer(GetType()); using (var ms = new System.IO.MemoryStream()) { serializer.WriteObject(ms, this); ms.Position = 0; return serializer.ReadObject(ms); } }
4 Réponses :
soit annotant vos classes avec [Datacontract] code> ou ajoutez vos types d'enfants dans le constructeur de DatacontractSerializer.
var knownTypes = new List<Type> {typeof(Class1), typeof(Class2), ..etc..};
var serializer = new DataContractSerializer(GetType(), knownTypes);
Vous avez besoin d'un sérialiseur binaire pour préserver l'identité des objets pendant l'étape de sérialisation / désérialisation. P>
Oui, mais j'utilise SQLMetal pour créer les classes et la gâchette / la sérialisation: unidirectionnel. Désolé pour la gêne occasionnée.
Je ne comprends pas comment votre commentaire est lié à ma réponse ...? Regardez l'échantillon de code fourni par Darin Dimitrov
Désolé @seb, mais ce n'est pas correct. DatacontractSerializer peut I> Copier des graphiques appropriés et n'est pas un sérialiseur binaire. Inversement, il n'est pas vrai que tous les sérialiszers binaires peuvent i> copier nécessairement des graphiques. Le support graphique et la production binaire sont des concepts orthogonaux.
@MARC Je pensais que la xmlserialisation ne parviendrait jamais à préserver l'identité d'objet. Ai-je tort ? Dans ce cas, comment puis-je le faire? [Je suis habitué à travailler avec .net 2.0 mais je suis nouveau à 3.0 et je n'ai pas encore travaillé sur 3,5, s'il vous plaît soyez doux ;-)]
Pour effectuer un clone profond, vous pouvez envisager d'utiliser un sérialiseur binaire:
public static object CloneObject(object obj) { using (var memStream = new MemoryStream()) { var binaryFormatter = new BinaryFormatter( null, new StreamingContext(StreamingContextStates.Clone)); binaryFormatter.Serialize(memStream, obj); memStream.Seek(0, SeekOrigin.Begin); return binaryFormatter.Deserialize(memStream); } }
Utilisez simplement la surcharge du constructeur qui accepte preserveobjectReferences code>, et définissez-la sur TRUE:
using System;
using System.Runtime.Serialization;
static class Program
{
public static T Clone<T>(T obj) where T : class
{
var serializer = new DataContractSerializer(typeof(T), null, int.MaxValue, false, true, null);
using (var ms = new System.IO.MemoryStream())
{
serializer.WriteObject(ms, obj);
ms.Position = 0;
return (T)serializer.ReadObject(ms);
}
}
static void Main()
{
Foo foo = new Foo();
Bar bar = new Bar();
foo.Bar = bar;
bar.Foo = foo; // nice cyclic graph
Foo clone = Clone(foo);
Console.WriteLine(foo != clone); //true - new object
Console.WriteLine(clone.Bar.Foo == clone); // true; copied graph
}
}
[DataContract]
class Foo
{
[DataMember]
public Bar Bar { get; set; }
}
[DataContract]
class Bar
{
[DataMember]
public Foo Foo { get; set; }
}
Duh! J'aurais dû chercher plus de notes! :)
Cela devrait être le meilleur moyen que je puisse voir ... merci Marc, mais j'ai un problème avec objet.Object2.Object3, peut-il être un problème sur le sérialisateur?
J'ai remarqué la même chose, cela pourrait aller quelques niveaux, mais surtout vous vous retrouvez avec un graphique partiel et inutile.
@Leppie - cela peut être fait, cependant ;-p