using System.Collections.Generic;
using System.Xml.Serialization;
using System.Diagnostics;
using System.ComponentModel;
string InputValue { get; set; }
public class Input1 : IInput
public string InputSource { get; set; }
public string InputValue { get; set; }
[XmlType(Namespace = "BarFoo")]
public class Input2 : IInput
public string InputName { get; set; }
public string InputValue { get; set; }
[XmlRoot(Namespace = JobInput.XmlNamespace)]
[XmlType(Namespace = JobInput.XmlNamespace)]
const string XmlNamespace = "";
public int AgencyId { get; set; }
public Guid ExternalId { get; set; }
public string Requester { get; set; }
public IInput Input { get; set; }
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
public XElement[] XmlCustomElements
var list = new List<XElement>();
list.Add(Input.SerializePolymorphicToXElement(XName.Get("Input", XmlNamespace)));
this.Input = value.DeserializePolymorphicEntry<IInput>(XName.Get("Input", XmlNamespace));
public static class XObjectExtensions
public static XmlSerializerNamespaces NoStandardXmlNamespaces()
var ns = new XmlSerializerNamespaces();
public static object Deserialize(this XContainer element, Type type, XmlSerializer serializer)
using (var reader = element.CreateReader())
return (serializer ?? new XmlSerializer(type)).Deserialize(reader);
public static XElement SerializeToXElement<T>(this T obj, XmlSerializerNamespaces ns, XmlSerializer serializer)
var doc = new XDocument();
using (var writer = doc.CreateWriter())
(serializer ?? new XmlSerializer(obj.GetType())).Serialize(writer, obj, ns);
const string TypeAttributeName = "AssemblyQualifiedName";
public static T DeserializePolymorphicEntry<T>(this XElement[] arrayValue, XName name)
var element = arrayValue.Where(e => e.Name == name).FirstOrDefault();
return element.DeserializePolymorphic<T>(name);
public static T DeserializePolymorphic<T>(this XElement value, XName name)
var typeName = (string)value.Attribute(TypeAttributeName);
throw new InvalidOperationException(string.Format("Missing AssemblyQualifiedName for \"{0}\"", value.ToString()));
var type = Type.GetType(typeName, true);
return (T)value.Deserialize(type, XmlSerializerFactory.Create(type, name));
public static XElement SerializePolymorphicToXElement<T>(this T obj, XName name)
var element = obj.SerializeToXElement(XObjectExtensions.NoStandardXmlNamespaces(), XmlSerializerFactory.Create(obj.GetType(), name));
foreach (var attr in element.Attributes().Where(a => a.IsNamespaceDeclaration).ToList())
element.Add(new XAttribute("AssemblyQualifiedName", obj.GetType().AssemblyQualifiedName));
public static class XmlSerializerFactory
static readonly object padlock;
static readonly Dictionary<Tuple<Type, XName>, XmlSerializer> serializers;
static XmlSerializerFactory()
serializers = new Dictionary<Tuple<Type, XName>, XmlSerializer>();
public static XmlSerializer Create(Type type, XName name)
throw new ArgumentNullException();
return new XmlSerializer(type);
XmlSerializer serializer;
var key = Tuple.Create(type, name);
if (!serializers.TryGetValue(key, out serializer))
serializers[key] = serializer = new XmlSerializer(type, new XmlRootAttribute { ElementName = name.LocalName, Namespace = name.NamespaceName });
public static class XmlExtensions
public static T LoadFromXML<T>(this string xmlString)
T returnValue = default(T);
using (StringReader reader = new StringReader(xmlString))
object result = new XmlSerializer(typeof(T)).Deserialize(reader);
public static string GetXml(this object obj)
using (var textWriter = new StringWriter())
var settings = new XmlWriterSettings() { Indent = true, IndentChars = " " };
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
new XmlSerializer(obj.GetType()).Serialize(xmlWriter, obj);
return textWriter.ToString();
public static void Test()
var test1 = new JobInput { AgencyId = 101, ExternalId = Guid.NewGuid(), Requester = "Joe", Input = new Input1 { InputValue = "foo value", InputSource = "Foo source" } };
Debug.Assert(false, ex.ToString());
var test2 = new JobInput { AgencyId = 101, ExternalId = Guid.NewGuid(), Requester = "Joe", Input = new Input2 { InputValue = "foo value", InputName = "input name" } };
Debug.Assert(false, ex.ToString());
private static void Test(JobInput test)
var test2 = xml.LoadFromXML<JobInput>();
var xml2 = test2.GetXml();
throw new InvalidOperationException("!(xml == xml2)");
if (test.Input.GetType() != test2.Input.GetType())
throw new InvalidOperationException("test.Input.GetType() != test2.Input.GetType()");
if (Newtonsoft.Json.JsonConvert.SerializeObject(test.Input) != Newtonsoft.Json.JsonConvert.SerializeObject(test2.Input))
throw new InvalidOperationException("Newtonsoft.Json.JsonConvert.SerializeObject(test.Input) != Newtonsoft.Json.JsonConvert.SerializeObject(test2.Input)");
public static void Main()
Console.WriteLine(typeof(Newtonsoft.Json.Linq.JToken).Assembly.FullName);