Prevent positional record from being serialized by XmlSerializer

46 Views Asked by At

I have simple C#9 positional record with an empty constructor (in addition to primary one):

public record FiscalTag(int Code, string Value, List<FiscalTag> ChildTags)
{
    public FiscalTag() : this(default, default, default) { }
}

How can I prevent it from being serialized by XmlSerializer? Records have EqualityContract (a compiler-genereated vitrual readonly property). This property creates problems in our serialization unit tests. So I need to disable serialization completely.

More info about our unit test problem: In our unit tests we gather all AutoProperties with:

var autoProps = Type.GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly
| BindingFlags.Public | BindingFlags.NonPublic)
.Where(property => property.CanRead 
&& property.GetGetMethod(true).IsDefined(typeof(CompilerGeneratedAttribute), false).ToList();

If we find any readonly AutoProperty or virtual AutoProperty in that list - we throw an exception (they are not supported by XmlSerializer).

Unlike ordinary AutoProperties (where CompilerGeneratedAttribute attribute is applied to getter and setter), EqualityContract property itself has CompilerGeneratedAttribute attribute applied. This property is not serialized - so it can be safely excluded from our list:

var autoProps = Type.GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly
| BindingFlags.Public | BindingFlags.NonPublic)
.Where(property => property.CanRead 
&& property.GetGetMethod(true).IsDefined(typeof(CompilerGeneratedAttribute), false)
&& !property.IsDefined(typeof(CompilerGeneratedAttribute)).ToList();
1

There are 1 best solutions below

0
Marc Gravell On

To intentionally break xml serialization, you could implement IXmlSerializable:

public record FiscalTag(int Code, string Value, List<FiscalTag> ChildTags) : IXmlSerializable
{
    public FiscalTag() : this(default, default!, default!) { }

    const string NotSerializable = "suitable message here";

    XmlSchema? IXmlSerializable.GetSchema() => throw new NotSupportedException(NotSerializable);

    void IXmlSerializable.ReadXml(XmlReader reader) => throw new NotSupportedException(NotSerializable);

    void IXmlSerializable.WriteXml(XmlWriter writer) => throw new NotSupportedException(NotSerializable);
}

This will at least give you a suitable message at runtime.