CSharp · Console
//Workaround for bug report: https://github.com/dotnet/runtime/issues/44701 (issue shown at https://dotnetfiddle.net/W9zCSm)
//Using XmlAttributeOverrides as suggested at https://social.msdn.microsoft.com/Forums/vstudio/en-US/4d70a9b9-0546-478b-8fd1-becee107106a/xmlserializer-fails-when-trying-to-serialize-hidden-property-with-xmlignore
using System;
using System.Xml;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.IO;
using System.Text;
public class Program
{
public static void Main()
{
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
//Override hiding of members (workarround for XmlIgnore being ignore if defined at descendant class)
//Override order for of members (without this you get E,G,C,D output order)
overrides.Add(typeof(ToSerialize), "A", new XmlAttributes { XmlIgnore = true, XmlElements = { new XmlElementAttribute(){ Order=1 } } });
overrides.Add(typeof(ToSerialize), "B", new XmlAttributes { XmlIgnore = true, XmlElements = { new XmlElementAttribute(){ Order=2 } } });
overrides.Add(typeof(ToSerialize), "C", new XmlAttributes { XmlIgnore = false, XmlElements = { new XmlElementAttribute(){ Order=3 } } } );
overrides.Add(typeof(ToSerialize), "G", new XmlAttributes { XmlIgnore = false, XmlAnyElements = { new XmlAnyElementAttribute(){ Order=4 } } } );
overrides.Add(typeof(ToSerialize), "D", new XmlAttributes { XmlIgnore = false, XmlElements = { new XmlElementAttribute(){ Order=5 } } } );
overrides.Add(typeof(ToSerialize), "H", new XmlAttributes { XmlIgnore = false, XmlAnyElements = { new XmlAnyElementAttribute(){ Order=6 } } } );
overrides.Add(typeof(ToSerialize), "E", new XmlAttributes { XmlIgnore = false, XmlElements = { new XmlElementAttribute(){ Order=7 } } } );
using(var stream = new MemoryStream()){
XmlSerializer xmlSer = new XmlSerializer(typeof(ToSerializeA), overrides); //typeof(ToSerialize)
xmlSer.Serialize(
stream,
//new ToSerialize(){}
new ToSerializeA(){ NoExtraComment = true } //set to false to show the extra comment for H (note that we've set XmlIgnore=false, but can still return an XmlComment or XmlSignificantWhitespace based on this flag)
);
stream.Position = 0;
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
string value = reader.ReadToEnd();
Console.WriteLine(value);
}
}
}
}
[Serializable]
public partial class ToSerialize
{
public const string MSG_SERIALIZABLE = "Serializable";
public const string MSG_NON_SERIALIZABLE = "Non-Serializable";
public string A { get; set;} = MSG_SERIALIZABLE;
public virtual string B { get; set;} = MSG_SERIALIZABLE;
[XmlIgnore]
public string C { get; set;} = MSG_NON_SERIALIZABLE;
[XmlIgnore]
public virtual string D { get; set;} = MSG_NON_SERIALIZABLE;
}
public partial class ToSerialize
{
[XmlIgnore]
public bool NoExtraComment = false;
public string E { get; set;} = MSG_SERIALIZABLE;
[XmlIgnore]
public string F { get; set;} = MSG_NON_SERIALIZABLE;
[XmlAnyElement(nameof(G))] //better have a name at XmlAnyElement, else WCF's serialization chokes on it even with every possible ignore attribute being used
[XmlIgnore, SoapIgnore, IgnoreDataMember] //to be overriden so that comment gets shown
public XmlCharacterData G {
get { return new XmlDocument().CreateComment("G (Comment)"); }
set {} //this is required, if missed it won't emit the comment
}
[XmlAnyElement(nameof(H))] //better have a name at XmlAnyElement, else WCF's serialization chokes on it even with every possible ignore attribute being used
[XmlIgnore, SoapIgnore, IgnoreDataMember] //not needed to ignore even via an AttributeOverride, will hide by returning a SignificantWhiteSpace //keeping it for other serialization clients
public XmlCharacterData H {
get {
return !NoExtraComment?
new XmlDocument().CreateComment("H (Comment)") :
new XmlDocument().CreateSignificantWhitespace("");
} //No comment
set {} //if this doesn't exists it will just be ignored
}
}
//-----------------------------------------
[Serializable]
public class ToSerializeA: ToSerialize
{
[XmlIgnore]
public new string A { get; set;} = MSG_NON_SERIALIZABLE; //BUG: SHOULDN'T SERIALIZE THIS
[XmlIgnore]
public override string B { get; set;} = MSG_NON_SERIALIZABLE; //BUG: SHOULDN'T SERIALIZE THIS
public new string C { get; set;} = MSG_SERIALIZABLE;
public override string D { get; set;} = MSG_SERIALIZABLE;
}