0

I need a way to customize C# XML (de)serialization mechanism in this way:

[Serializable]
public class MyElement : IXmlSerializable
{
    [XmlAttribute]
    public string PropertyX { get; set; }

    [XmlElement]
    public MySubElement SubElement { get; set; }

    // .... other properties and elements...

    [XmlIgnore]
    public string ElementXml { get;set; }


    public XmlSchema GetSchema() { return null; }

    public void ReadXml(XmlReader reader)
    {
        // use default deserialization mechanism, like IXmlSerializable isn't implemented
    }

    public void WriteXml(XmlWriter writer)
    {
        if (!string.IsNullOrEmpty(ElementXml)) {
            // serialize as ElementXml value
        }
        else 
        {
            // serialize using default serialization mechanism, like IXmlSerializable isn't implemented
        }
    }
}

I need to use this paradigm on multiple elements, for instance MySubElement should also behave like this. Object model is complex, so implementing this attribute by attribute or element by element isn't an option for me. Can this be done?

Filip
  • 3,257
  • 2
  • 22
  • 38
  • at some point you have to do that somehow, also see this https://stackoverflow.com/questions/1495716/net-xmlignore-by-default – aybe Oct 09 '17 at 15:02
  • In the case where `ElementXml` is populated, will the other members such as `PropertyX` have default (null) values? – dbc Oct 09 '17 at 22:15
  • @dbc I can make them have default values if that will solve problem. – Filip Oct 10 '17 at 07:29
  • Then you might consider a different architecture. Instead of `IXmlSerializable` you could have an [`[XmlAnyElement] public XmlNode [] ElementXml { get; set; }`](https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlanyelementattribute.aspx) property. If all the other properties are `null` (either null reference types or nullable value types) then `XmlSerializer` won't serialize them by default, and only your `ElementXml` will get serialized. – dbc Oct 10 '17 at 11:21
  • There's also [`[XmlAnyAttribute] public XmlAttribute[] XAttributes { get; set; }`](https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlanyattributeattribute.aspx) for emitting arbitrary attributes of `MyElement`. – dbc Oct 10 '17 at 11:29
  • @Filip, I'm exactly in the same situation. Did you happen to find any solution? – ANewGuyInTown Jul 07 '22 at 01:03

1 Answers1

0

Consider using System.ComponentModel.DefaultValue attribute.

public class MyElement
{
    [XmlAttribute]
    public string PropertyX { get; set; }

    [XmlElement]
    public MySubElement SubElement { get; set; }

    [DefaultValue("")]
    public string ElementXml { get; set; }
}

If ElementXml is string.Empty, then it will not be serialized.

You should probably use code like this:

private string _elementXml;

[DefaultValue("")]
public string ElementXml
{
    get => _elementXml;
    set => _elementXml = string.IsNullOrWhiteSpace(value) ? null : value;
}

In this case, will not be serialized not only null or empty, but also any string of whitespace.

Alexander Petrov
  • 13,457
  • 2
  • 20
  • 49
  • 1
    what part of my problem this solves? Skipping ElementXml serialization isn't problem, I can do that with ShouldSerialize methods also. I need solution for parts of code with comments. – Filip Oct 10 '17 at 07:32
  • @Filip - it uses default serialization mechanism, without `IXmlSerializable` implementation. – Alexander Petrov Oct 10 '17 at 09:14