Erstellen Zeiger auf geordnete Objekt in Deserialisierung in C #

stimmen
4

Ich habe ein Klasse wie:

[Serializable]
public class child {
     public Parent parent;
}

[Serializable]
public class Parent {
  public List<child> children;
}

Wenn ich Eltern deserialisieren, mag ich jedes Kind jeweils eine Referenz haben, um es Eltern. Die Frage ist, wo in der Deserialisierung kann es das Kind „Eltern“ Zeiger gesetzt? Ich kann nicht einen benutzerdefinierten Konstruktor zu verwenden, für ein Kind erscheinen, weil Deserialisierung immer das Standard-Konstruktor verwendet. Wenn ich ISerializable implementieren, dann scheint es, dass das Kind sich bereits von der Zeit erstellt wurde, wird die Eltern erstellt. Gibt es eine andere Möglichkeit, dies zu erreichen?

Veröffentlicht am 09/12/2008 um 18:20
quelle vom benutzer
In anderen Sprachen...                            


4 antworten

stimmen
2

Wenn Sie es in Ruhe lassen und lassen Eltern eine öffentliche Lese / Schreib-Eigenschaft des Kindes Klasse, wird .NET automatische Serialisierung es richtig handhaben.

Beantwortet am 09/12/2008 um 18:28
quelle vom benutzer

stimmen
0

Ich erreicht diese (Art) durch die Add-Methode in der Sammlung Klasse des Objekts Kind überschreiben, auf ‚“ Eigenschaftswert in der Kind-Klasse mit dem einzigartigen Identifikator des übergeordneten Objekts

 public class Connections: List<Connection>
    {       public new void Add(Connection connection)
        {
            connection.ApplicationName = ApplicationName;
            base.Add(connection);
        }
    }
Beantwortet am 09/12/2008 um 18:31
quelle vom benutzer

stimmen
2

Wenn die automatische Deserialisierung nicht funktioniert, könnten Sie Ihre Eltern Klasse haben die Umsetzung IDeserializationCallback Schnittstelle , und die Kinder in der Aktualisierung OnDeserialization Methode .

[Serializable]
class Parent : IDeserializationCallback 
{
  public List<child> children;

  void IDeserializationCallback.OnDeserialization(Object sender) 
  {
    if (null != children)
    {
      children.ForEach(c => c.parent = this);
    }
  }
}
Beantwortet am 16/03/2012 um 19:52
quelle vom benutzer

stimmen
8

Zirkuläre Referenzen sind unterschiedlich für die Handhabung BinaryFormatter, XmlSerializerund DataContractSerializer.

Die BinaryFormatterStützen zirkuläre Referenzen standardmäßig keine Arbeit erforderlich:

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
public class Child
{
    public Guid Id { get; set; }

    public Parent parent;
}

[Serializable]
public class Parent
{
    public Guid Id;

    public List<Child> Children;
}

class Program
{
    static void Main(string[] args)
    {
        Child c1 = new Child { Id = Guid.NewGuid() };
        Child c2 = new Child { Id = Guid.NewGuid() };

        Parent p = new Parent { Id = Guid.NewGuid(), Children = new List<Child> { c1, c2 } };

        c1.parent = p;
        c2.parent = p;

        using (var stream1 = new MemoryStream())
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream1, p);
            stream1.Position = 0;

            var deserializedParent = formatter.Deserialize(stream1) as Parent;
            foreach (var child in deserializedParent.Children)
            {
                Console.WriteLine("Child Id: {0}, Parent Id: {1}", child.Id, child.parent.Id);
            }
        }

        Console.ReadLine();
    }
}

Wenn die Verwendung XmlSerializer, vermeiden den Kreis refernce durch nicht das Kind Bezug auf die Mutter Serialisierung und sicherzustellen , dass die Beziehung während der Deserialisierung festgelegt ist. Dies wird durch die Umsetzung der getan IXmlSerializableSchnittstelle und Umgang mit Serialisierung und Deserialisierung.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace XmlSerialization
{

    [Serializable]
    public class Child
    {
        public Guid Id { get; set; }

        [XmlIgnore] // Don't serialize the reference to the parent
        public Parent parent;
    }

    [Serializable]
    public class Parent : IXmlSerializable
    {
        public List<Child> Children;

        public Guid Id;

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            XElement xml = XElement.ReadFrom(reader) as XElement;
            if (xml != null)
            {
                // Deserialize Children
                Children = 
                    xml.Descendants("Child")
                       .Select(x => new Child() { Id = Guid.Parse(x.Element("Id").Value), parent = this })
                       .ToList();

                // Deserialize Id
                Id = Guid.Parse(xml.Attribute("Id").Value); 
            }
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            // Serialize Id
            writer.WriteAttributeString("Id", Id.ToString());

            // Serialize Children
            XmlSerializer childSerializer = new XmlSerializer(typeof(Child));
            foreach (Child child in Children)
            {
                childSerializer.Serialize(writer, child);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Child c1 = new Child { Id = Guid.NewGuid() };
            Child c2 = new Child { Id = Guid.NewGuid() };

            Parent p = new Parent { Id = Guid.NewGuid(), Children = new List<Child> { c1, c2 } };

            c1.parent = p;
            c2.parent = p;

            using (var stream1 = new MemoryStream())
            {
                XmlSerializer formatter = new XmlSerializer(typeof(Parent), new Type[] { typeof(Child) }) ;
                formatter.Serialize(stream1, p);
                stream1.Position = 0;

                stream1.Position = 0;

                var deserializedParent = formatter.Deserialize(stream1) as Parent;
                foreach (var child in deserializedParent.Children)
                {
                    Console.WriteLine(string.Format("Child Id: {0}, Parent Id: {1}", child.Id,  child.parent.Id ));
                }
            }

            Console.ReadLine();
        }

    }
}

Wenn die Verwendung DataContractSerializerVerwenden Sie die IsReference Eigenschaft des DataContractAttributs Referenznachführmerkmal zu ermöglichen , wenn die Serialisierung und Deserialisierung Datacontracts.

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

[DataContract(IsReference = true)]
public class Child
{
    [DataMember]
    public Guid Id { get; set; }

    [DataMember]
    public Parent parent;
}

[DataContract(IsReference = true)]
public class Parent
{
    [DataMember]
    public Guid Id;

    [DataMember]
    public List<Child> Children;
}

class Program
{
    static void Main(string[] args)
    {
        Child c1 = new Child { Id = Guid.NewGuid() };
        Child c2 = new Child { Id = Guid.NewGuid() };

        Parent p = new Parent { Id = Guid.NewGuid(), Children = new List<Child> { c1, c2 } };

        c1.parent = p;
        c2.parent = p;

        using (var stream1 = new MemoryStream())
        {
            DataContractSerializer formatter = new DataContractSerializer(typeof(Parent));
            formatter.WriteObject(stream1, p);
            stream1.Position = 0;

            var deserializedParent = formatter.ReadObject(stream1) as Parent;
            foreach (var child in deserializedParent.Children)
            {
                Console.WriteLine("Child Id: {0}, Parent Id: {1}", child.Id, child.parent.Id);
            }
        }

        Console.ReadLine();
    }

}
Beantwortet am 16/03/2012 um 20:37
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more