Laden...

Deserialization: XmlNode to object

Erstellt von syn87 vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.117 Views
S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren
Deserialization: XmlNode to object

Hallo und Tag,

ich bin zur Zeit etwas im Bereich "Verteilte Anwendungen" tätig.

Plugins können ein Objekt zur Speicherung anmelden:


SettingsRegister(object o);

Das Objekt wird dann automatisch beim Beenden der Anwendung zusammen mit allen anderen Settings in einer datei gespeichert.
Soweit klappt das auch alles ganz gut und er legt die XML-Datei korrekt an.
Ein Problem besteht momentan noch in der Deserialisierung der Objekte. Nach Start der Anwendung melden sich die Plugins zeitversetzt an. D.h. insbesondere, dass ich die Typdefinitionen nicht sofort zur Verfügung habe. Resultat dessen ist, dass alle Objekte, die mit SettingsRegister angemeldet wurden, nun zunächst als XMLNode[] vorliegen. Nun kommt die Frage: Kann man einen XMLNode nachträglich deserialisieren?

Meine momentane Lösung besteht darin, die XML-Datei erneut einzulesen, wenn das Plugin nach seinem Objekt fragt:


SettingsFetch(Type t);

Denn dann habe ich die Typdefinition und kann das Objekt finden. Nicht schön, aber selten.

Wäre schön wenn jemand eine Idee hätte.

Gruß,

Matze

2.760 Beiträge seit 2006
vor 14 Jahren

Nun da stellt sich als erstes die Frage wie (de)serialisierst du?
Ich habe es mal so glöst das jedes Plugin einen eindeutigen Bezeichner hat und anhand dessen eine Art ConfigSection im Config-File erstellt wird über die nur die Host-Anwendung und das entsprechende Plugin verfügen kann. Das Plugin muss sich dann selbst darüm kümmern das die Einstellungen geladen und gespeichert werden (Hat in der SDK natürlich einige Tools dafür zur Verfügung).

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

class SettingsCollection
{
        [XmlElement("Settings")]
        public List<object> objs = new List<object>();

        [XmlIgnore]
        protected List<Type> types = new List<Type>();

        public void Save()
        {
            XmlSerializer serializer = new XmlSerializer(this.GetType(), types.ToArray());
            FileStream fs = new FileStream("configs\\settings.xml", FileMode.Create);
            serializer.Serialize(fs, this);
        }

        public bool Register(object o)
        {
            Type t = o.GetType();
            if (types.Contains(t))
                return false;

            objs.Add(o);
            types.Add(t);
            return true;
        }
}

Der Output sieht dann z.b. so aus:


<?xml version="1.0"?>
<SettingsCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Settings xsi:type="MainFormSettings">
    <Kuuuh>kuscheln</Kuuuh>
  </Settings>
</SettingsCollection>

Gruß,

Matze

203 Beiträge seit 2006
vor 14 Jahren

was passier denn, wenn du jetzt einfach folgendes machst


public static SettingsCollection Load()
{
   SettingsCollection  retval = null;
   try
   {
      XmlSerializer serializer = new XmlSerializer(typeof(SettingsCollection));
      using(FileStream fs = new FileStream("configs\\settings.xml", FileMode.Open))
          retval = (SettingsCollection)serializer.Deserialize(fs);
      foreach (object o in retval.objs)
         retval.types.add(o.GetType());
  }
  catch {
  }
  return retval;
}

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Wenn ich beim deserialisieren den Typ der Objekte nicht kenne, werden daraus XMLNode[] Objekte.

203 Beiträge seit 2006
vor 14 Jahren

hmm schade, ich hatte gehofft, dass die xsi:type="MainFormSettings" genutzt würde.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Nein, wie auch. Zur Typdefinition bedarf es sicherlich etwas mehr als dem Namen. Trotzdem danke. Vielleicht hat noch wer ne idee.