Deserizalizacja XML i domyślne wartości właściwości klas

0

Witam. W swojej aplikacji przechowuję ustawienia w postaci klasy serializowanej do XML. Wygląda ona tak:

    [Serializable]
    public class Settings
    {
        [XmlAttribute("opt1"]
        public string Opt1 { get; set; }

        [XmlAttribute("opt2")]
        public int Opt2 { get; set; }

        public Settings() { }
    }

W momencie gdy deserializuję XML-a z pliku i brakuje któregoś z atrybutu, np. opt1, ustawiana jest dla niego wartość null (lub 0 w przypadku typu int). Istnieje jakiś mechanizm który podczas deserializacji przypisałby odpowiednim właściwiościom domyślne określone wartości? Czy trzeba to robić "na piechotę" sprawdzając każdą właściwość osobno?

0

zamiast propert użyj pól i przypisz im wartości, jeśli nie to możesz użyć zwykłego publicznego konstruktora (bez parametrów) i w nim przypisać domyślne wartości dla propert.

0

Schematem XML powinno się to robić. W nim można domyślne wartości ustawiać i XmlSerializer weźmie je pod uwagę.

0
Rev napisał(a)

Schematem XML powinno się to robić. W nim można domyślne wartości ustawiać i XmlSerializer weźmie je pod uwagę.

XML Schema zdaje się być tym czego szukałem, ale nie moge sobie z tym poradzić..

Kod mojej klasy:

    [Serializable]
    public class Settings
    {
        [XmlAttribute("opt1")]
        public string Opt1 { get; set; }

        [XmlAttribute("opt2")]
        public int Opt2 { get; set; }

        public Settings() { }
    }

Tak wygląda jej schemat XML:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Settings"
    targetNamespace="http://tempuri.org/Settings.xsd"
    xmlns="http://tempuri.org/Settings.xsd"
    xmlns:mstns="http://tempuri.org/Settings.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified"
>

  <xs:element name="Settings">
    <xs:complexType>
      <xs:attribute name="opt1" default="Domyślna wartość">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:minLength value="0" />
            <xs:maxLength value="20" />
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="opt2" default="50">
        <xs:simpleType>
          <xs:restriction base="xs:int">
            <xs:minInclusive value="0" />
            <xs:maxInclusive value="100" />
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>
  
</xs:schema>

A w taki sposób deserializuję plik XML z ustawieniami:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(Settings));
XmlSchema xmlSchema = XmlSchema.Read(new StreamReader("Settings.xsd"), (sender, e) =>
    {
        MessageBox.Show(e.Message);
    });
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.Schemas.Add(xmlSchema);
xmlReaderSettings.ValidationType = ValidationType.Schema;
xmlReaderSettings.ValidationFlags = XmlSchemaValidationFlags.ProcessIdentityConstraints | XmlSchemaValidationFlags.ReportValidationWarnings;

using (XmlReader xmlReader = XmlReader.Create(new StreamReader("settings.xml"), xmlReaderSettings))
{
    settings = (Settings)xmlSerializer.Deserialize(xmlReader);
}            

W pliku "settings.xml" brakuje obydwu atrybutów, deserializuje się bez problemu, jednak nadal ten sam efekt: opt1="", opt2=0. Dlaczego?? Mógłby mnie ktoś naprowadzić co robię źle?

0

OK, częściowo rozwiązałem swój problem. Wystarczyło dodać atrybut do klasy Settings:

[XmlRootAttribute(Namespace = "http://tempuri.org/Settings.xsd", IsNullable = false)]

Teraz gdy w pliku XML brakuje któregoś atrybutu, ustawiana jest dla niego wartość domyślna określona w XSD. Jednak kiedy jakiś atrybut istnieje, ale ma nieprawidłowy format (np. w 'opt2' zamiast liczby int jest łańcuch), podczas deserializacji wyrzucany jest wyjątek. Da się w jakiś sposób zrobić tak, aby wyjątek nie był rzucany, a była ustawiana wartość domyślna dla atrybutu (tak samo jak gdyby ten atrybut w ogóle nie istniał) ??

1 użytkowników online, w tym zalogowanych: 0, gości: 1