Laden...

XmlSerialisierung - neue boolsche Property da nicht in Xml vorhanden als true laden

Erstellt von inflames2k vor 9 Jahren Letzter Beitrag vor 9 Jahren 1.663 Views
inflames2k Themenstarter:in
2.298 Beiträge seit 2010
vor 9 Jahren
XmlSerialisierung - neue boolsche Property da nicht in Xml vorhanden als true laden

Hallo,

ich habe ein Programm, in dem Konfigurationen mittels Xml-Serialisierung gespeichert und geladen werden.

Die Konfiguration wurde um eine Markierung als "Aktiv" (Active) erweitert. Diese ist vom Typ boolean. An sich bis hier hin alles kein Problem.

Das Flag soll beim Laden im Programm ausgewertet werden und die zugehörigen Aktionen für die Konfiguration nur ausgeführt werden, wenn diese als Aktiv markiert ist.

Nun ist es so, dass das Programm bereits beim Kunden im Einsatz ist. Dort befindet sich das "Active"-Flag noch nicht in den Konfigurationsdateien. Bei der Deserialisierung wird dieses also als False gelesen und somit alle Einträge als Inaktiv gewertet. - Bei > 500 Einträgen, kann ich dem Benutzer jedoch nicht zumuten, alle Konfigurationen manuell zu aktivieren.

Welches vorgehen würdet ihr hier empfehlen?

Mir fällt dazu momentan nichts ein, außer das boolsche Flag evtl. Nullable zu setzen. Beim Laden würde es dann, wenn der Wert Null ist auf true gesetzt. Spricht da irgendwas dagegen? Habt ihr eventuell bessere Vorschläge dafür?

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

16.840 Beiträge seit 2008
vor 9 Jahren

Beim Laden würde es dann, wenn der Wert Null ist auf true gesetzt. Spricht da irgendwas dagegen? Habt ihr eventuell bessere Vorschläge dafür?

Das ist eine Möglichkeit; oder Du übernimmst die Serialisierung selbst.
Bei XML sowie bei DBs mach ich das mittlerweile auch so; so kann ich Defaultwerte für neue Werte selbst setzen und bin flexibler in der Anpassung.

742 Beiträge seit 2005
vor 9 Jahren

Setzt das Flag doch einfach im Konstruktor auf true

inflames2k Themenstarter:in
2.298 Beiträge seit 2010
vor 9 Jahren

~~Hallo malignate,

wenn ich mich nicht ganz täusche dürfte das keinen Einfluss haben, da das Flag ja durch die Deserialisierung auf "false" gesetzt würde. Da ist egal, was im Konstruktor steht.~~

Also bleibe ich bei dem Weg mit dem Nullable<bool>. - Scheint auch ganz gut zu funktionieren.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

742 Beiträge seit 2005
vor 9 Jahren

Der Serializer deserialisiert, nur wenn auch wirklich vorhanden, probiers doch aus:


public class Program
    {
        public class Container
        {
            [XmlElement("Item")]
            public List<Item> Items { get; set; }
        }

        public class Item
        {
            public bool Flag { get; set; }

            public Item()
            {
                Flag = true;
            }
        }

        static void Main(string[] args)
        {
            string xml = @"<Container><Item /><Item /></Container>";

            StringReader reader = new StringReader(xml);

            XmlSerializer serializer = new XmlSerializer(typeof(Container));

            Container container = (Container)serializer.Deserialize(reader);

            foreach (var item in container.Items)
            {
                Console.WriteLine(item.Flag);
            }
        }
    }

inflames2k Themenstarter:in
2.298 Beiträge seit 2010
vor 9 Jahren

Habs ja ausprobiert, drum hatte ich den Satz ja durchgestrichen. 🤔

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

T
708 Beiträge seit 2008
vor 9 Jahren

Ein anderer Lösungsansatz wären Properties.
Wenn der XmlSerializer keinen Knoten findet, wird der Initialwert verwendet.


    public class Item
    {
        private bool _flag = true;

        public bool Flag
        {
            get { return _flag; }
            set { _flag = value; }
        }
    }

Ist imho auch sauberer mit Properties zu arbeiten, da man gerade bei der Serialisierung auch ab und an Konvertierungen ausführen muss.
Man kann auch einfach die Einrichtung zurücksetzen, indem man das XML löscht. Finde ich auch praktisch 😃

Der Resharper meckert zwar immer, wenn man Getter & Setter nicht verändert (Convert to Auto-Property), aber ich finde es besser eine gleiche Struktur zu haben als zu mischen.

inflames2k Themenstarter:in
2.298 Beiträge seit 2010
vor 9 Jahren

Erstens, ohne Properties funktioniert Serialisierung nur mit Public fields und die verwende ich für sowas nicht.

Zweitens funktioniert der Ansatz nicht. Das war das erste was ich versuchte, drum ging ich auch davon aus, der Konstruktor mit Zuweisung zur Property würde nicht reichen. - Was jedoch der Fall ist.

Mit deinem Ansatz hatte ich immer das Verhalten, das der Wert nach der Deserialisierung false war.

Funktioniert haben also nur der Weg über Nullable bool mit


if(value == null) 
    _backingField = false;

und der Konstruktor.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

2.080 Beiträge seit 2012
vor 9 Jahren

Also entweder du legst irgendwo einen Standard-Wert an, der dann genommen wird, wenn das Flag nicht vorhanden ist, oder du baust irgendwo (z.B. in der Installations-Routine) eine Konvertierung ein, die in jeder Datei dieses entsprechende Flag setzt.

Die zweite Variante finde ich besser, da dann dort nichts im "Verborgenen" fest gelegt is. Jede einzelne Einstellung, die da drin steht, steht auch da drin und es wird nichts interpretiert, wie z.B. "nicht vorhanden" = "true"

So eine Konvertierung lässt sich bestimmt auch ohne großen Aufwand regeln.
Bei dem XmlSerializer wäre das ja nix Anderes, als Daten deserialisieren, überall das Flag auf true setzen und anschließend über die selbe Datei wieder serialisieren, zumindest wenn sicher gestellt ist, dass die konvertierten Dateien wirklich zur älteren Version gehören.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo inflames2k,

aus meiner Sicht spricht nichts gegen die Verwendung eines Defaultwerts. Ich habe es nicht probiert, aber vielleicht klappt das sogar einfach mit einem DefaultValueAttribute für die Property.

Eine Konvertierung bestehender Dateien hat in bestimmten Situationen Nachteile, insbesondere wenn es nicht möglich ist, in einer Einmalaktion alle jetzt und in Zukunft benötigten Dateien zu konvertieren.

Der Vollständigkeit halber: Bei der binären Serialisierung gibt es die Möglichkeit der Versionstoleranten Serialisierung. Keine Ahnung ob oder wieviel sich davon auf die XML-Serialisierung übertragen lässt.

herbivore

S
145 Beiträge seit 2013
vor 9 Jahren

aus meiner Sicht spricht nichts gegen die Verwendung eines Defaultwerts. Ich habe es nicht probiert, aber vielleicht klappt das sogar einfach mit einem DefaultValueAttribute für die Property.

Klappt auch, würde sogar die XML Datei verkleinern da nur die Eigenschaften serialisiert werden deren werde nicht laut DefaultValueAttribute sind.

742 Beiträge seit 2005
vor 9 Jahren

Ich glaube DefaultValue klappt nur bei der Serialisierung, ist aber nur eine vage Vermutung.