CSharp · Console
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Diagnostics;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.XPath;
using System.Runtime.Serialization;
using System.ComponentModel;
public interface IClassName
{
string Child1 { get; set; }
string Child2 { get; set; }
}
namespace V1
{
[XmlRoot("ClassName")]
//[DataContract]
public class ClassName : IClassName
{
//[DataMember]
[XmlElement("Child1")]
public string Child1 { get; set; }
//[DataMember]
[XmlElement("Child2", IsNullable = true)]
public string Child2 { get; set; }
}
}
namespace V2
{
public struct CustomXmlNilTextWrapper
{
bool forceNull;
string value;
public static implicit operator CustomXmlNilTextWrapper(string value)
{
return new CustomXmlNilTextWrapper(value);
}
public static implicit operator string(CustomXmlNilTextWrapper wrapper)
{
return wrapper.Value;
}
public CustomXmlNilTextWrapper(string value)
{
this.value = value;
this.forceNull = value == null;
}
[XmlAttribute("nil")]
public bool ForceNull { get { return forceNull; } set { forceNull = value; } }
public bool ShouldSerializeForceNull() { return ForceNull == true; }
[XmlText]
public string Value { get { return ForceNull ? null : value ?? string.Empty; } set { this.value = value; } }
}
[XmlRoot("ClassName")]
//[DataContract]
public class ClassName : IClassName
{
//[DataMember]
[XmlElement("Child1")]
public string Child1 { get; set; }
//[DataMember]
[XmlIgnore]
public string Child2 { get; set; }
[XmlElement("Child2")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
//[IgnoreDataMember]
public CustomXmlNilTextWrapper Child2Xml { get { return Child2; } set { Child2 = value; } }
}
}
public static class XmlSerializationHelper
{
public static T LoadFromXML<T>(this string xmlString)
{
using (StringReader reader = new StringReader(xmlString))
{
return (T)new XmlSerializer(typeof(T)).Deserialize(reader);
}
}
public static string GetXml<T>(this T obj)
{
using (var textWriter = new StringWriter())
{
var settings = new XmlWriterSettings() { Indent = true, IndentChars = " " }; // For cosmetic purposes.
var ns = new XmlSerializerNamespaces();
ns.Add("", ""); // Suppress default namespaces.
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
new XmlSerializer(obj.GetType()).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();
}
}
}
public static class ConsoleAndDebug
{
public static void WriteLine(object s)
{
Console.WriteLine(s);
Debug.WriteLine(s);
}
}
public class TestClass
{
public static void Test()
{
ConsoleAndDebug.WriteLine("XML serialization test for custom nil attribute:");
Test<V2.ClassName>();
ConsoleAndDebug.WriteLine("XML serialization test for standard nil attribute:");
Test<V1.ClassName>();
}
public static void Test<ClassName>() where ClassName : IClassName, new()
{
ConsoleAndDebug.WriteLine(string.Format("XML output for \"{0}\":\n", typeof(ClassName).FullName));
var strings = new[] { null, string.Empty, "FooBar" };
for (int iChild1 = 0; iChild1 < strings.Length; iChild1++)
{
for (int iChild2 = 0; iChild2 < strings.Length; iChild2++)
{
var test = new ClassName() { Child1 = strings[iChild1], Child2 = strings[iChild2] };
var xml = test.GetXml();
var testS1 = strings[iChild1] != null ? '"' + strings[iChild1] + '"' : "null";
var testS2 = strings[iChild2] != null ? '"' + strings[iChild2] + '"' : "null";
ConsoleAndDebug.WriteLine(string.Format("Output for Child1 = {0} and Child2 = {1}", testS1, testS2));
ConsoleAndDebug.WriteLine(xml);
ConsoleAndDebug.WriteLine("");
var test2 = xml.LoadFromXML<ClassName>();
if (test2.Child2 != test.Child2)
{
throw new InvalidOperationException("Child2 value not deserialized correctly");
}
}
}
ConsoleAndDebug.WriteLine("");
}
}
public class Program
{
public static void Main()
{
TestClass.Test();
}
}