Ich erhalte eine Xml von der 3. Partei und ich muss es in C#-Objekt zu deserialisieren. Diese Xml kann Attribute mit Wert von Integer-Typ oder leeren Wert enthalten: attr="11" oder attr="". Ich möchte dieses Attribut Wert in die Eigenschaft mit dem Typ der nullable Integer zu deserialisieren. Aber XmlSerializer unterstützt keine Deserialisierung in nullable Typen. Der folgende Testcode schlägt bei der Erstellung von XmlSerializer mit InvalidOperationException {"There was an error reflecting type 'TestConsoleApplication.SerializeMe'."} fehl.
[XmlRoot("root")]
public class SerializeMe
{
[XmlElement("element")]
public Element Element { get; set; }
}
public class Element
{
[XmlAttribute("attr")]
public int? Value { get; set; }
}
class Program {
static void Main(string[] args) {
string xml = "<root><element attr=''>valE</element></root>";
var deserializer = new XmlSerializer(typeof(SerializeMe));
Stream xmlStream = new MemoryStream(Encoding.ASCII.GetBytes(xml));
var result = (SerializeMe)deserializer.Deserialize(xmlStream);
}
}
Wenn ich den Typ der Eigenschaft "Value" in int ändere, schlägt die Deserialisierung mit InvalidOperationException fehl:
Es gibt einen Fehler im XML-Dokument (1, 16).
Kann jemand beraten, wie zu deserialize Attribut mit leeren Wert in nullable Typ (als null) zur gleichen Zeit deserializing nicht leeren Attributwert in die Ganzzahl? Gibt es einen Trick dafür, so dass ich nicht zu tun haben, Deserialisierung jedes Feldes manuell (tatsächlich gibt es eine Menge von ihnen)?
Update nach Kommentar von ahsteele:
-
Soweit ich weiß, funktioniert dieses Attribut nur mit XmlElementAttribute - dieses Attribut gibt an, dass das Element keinen Inhalt hat, weder Kindelemente noch Textkörper. Aber ich muss die Lösung für XmlAttributeAttribute finden. Auf jeden Fall kann ich xml nicht ändern, weil ich keine Kontrolle darüber habe.
-
Diese Eigenschaft funktioniert nur, wenn der Attributwert nicht leer ist oder wenn das Attribut fehlt. Wenn attr einen leeren Wert hat (attr=''), schlägt der XmlSerializer-Konstruktor (wie erwartet) fehl.
public class Element { [XmlAttribute("attr")] public int Value { get; set; } [XmlIgnore] public bool ValueSpecified; }
-
Benutzerdefinierte nullbare Klasse wie in diesem Blogbeitrag von Alex Scordellis
Ich habe versucht, die Klasse aus diesem Blogbeitrag auf mein Problem anzuwenden:
[XmlAttribute("attr")] public NullableInt Value { get; set; }
Aber XmlSerializer Konstruktor schlägt mit InvalidOperationException:
Das Mitglied 'Value' vom Typ TestConsoleApplication.NullableInt kann nicht serialisiert werden.
XmlAttribute/XmlText können nicht verwendet werden, um Typen zu kodieren, die IXmlSerializable implementieren }
-
Hässliche Surrogatlösung (Schande über mich, dass ich diesen Code hier geschrieben habe :) ):
public class Element { [XmlAttribute("attr")] public string SetValue { get; set; } public int? GetValue() { if ( string.IsNullOrEmpty(SetValue) || SetValue.Trim().Length <= 0 ) return null; int result; if (int.TryParse(SetValue, out result)) return result; return null; } }
Aber ich möchte nicht mit der Lösung wie diese kommen, weil es bricht Schnittstelle meiner Klasse für seine Verbraucher. Ich würde besser manuell implementieren IXmlSerializable Schnittstelle.
Derzeit sieht es aus wie ich IXmlSerializable für die gesamte Element-Klasse (es ist groß) zu implementieren und es gibt keine einfachen Workaround
1 Stimmen
Dieses Problem plagt mich schon seit einem Jahrzehnt. Gibt es keinen einfachen Dekorator, der dieses Problem im Jahr 2021 löst?