using System.Collections.Generic;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public AListObject AList { get; set; }
public List<A> SerializedListObjects { get; set; }
public class ComplexRootObject
public MidObjectDerived MidObject { get; set; }
public List<A> SerializedListObjects { get; set; }
public List<A> AnotherSerializedListObjects { get; set; }
public class MidObjectDerived : MidObject
public List<A> DerivedSerializedListObjects { get; set; }
public interface IXmlSerializerFactory
XmlSerializer CreateSerializer(Type rootType);
public static class AListSerializerFactory
static readonly XmlArrayItemTypeOverrideSerializerFactory instance;
static AListSerializerFactory()
var declaringTypeList = new []
var derivedTypesList = new Dictionary<Type, Func<IEnumerable<Type>>>
{ typeof(A), () => new [] { typeof(B), typeof(C) } },
instance = new XmlArrayItemTypeOverrideSerializerFactory(declaringTypeList, derivedTypesList);
public static IXmlSerializerFactory Instance { get { return instance; } }
public class XmlArrayItemTypeOverrideSerializerFactory : IXmlSerializerFactory
readonly object padlock = new object();
readonly Dictionary<Type, XmlSerializer> serializers = new Dictionary<Type, XmlSerializer>();
readonly XmlAttributeOverrides overrides;
public XmlArrayItemTypeOverrideSerializerFactory(IEnumerable<Type> declaringTypeList, IEnumerable<KeyValuePair<Type, Func<IEnumerable<Type>>>> derivedTypesList)
var completed = new HashSet<Type>();
overrides = declaringTypeList
.SelectMany(d => derivedTypesList.Select(p => new { declaringType = d, itemType = p.Key, derivedTypes = p.Value() }))
.Aggregate(new XmlAttributeOverrides(), (a, d) => a.AddXmlArrayItemTypes(d.declaringType, d.itemType, d.derivedTypes, completed));
public XmlSerializer CreateSerializer(Type rootType)
XmlSerializer serializer;
if (!serializers.TryGetValue(rootType, out serializer))
serializers[rootType] = serializer = new XmlSerializer(rootType, overrides);
public static partial class XmlAttributeOverridesExtensions
public static XmlAttributeOverrides AddXmlArrayItemTypes(this XmlAttributeOverrides overrides, Type declaringType, Type itemType, IEnumerable<Type> derivedTypes)
return overrides.AddXmlArrayItemTypes(declaringType, itemType, derivedTypes, new HashSet<Type>());
public static XmlAttributeOverrides AddXmlArrayItemTypes(this XmlAttributeOverrides overrides, Type declaringType, Type itemType, IEnumerable<Type> derivedTypes, HashSet<Type> completedTypes)
if (overrides == null || declaringType == null || itemType == null || derivedTypes == null || completedTypes == null)
throw new ArgumentNullException();
XmlAttributes attributes = null;
for (; declaringType != null && declaringType != typeof(object); declaringType = declaringType.BaseType)
if (!completedTypes.Add(declaringType))
foreach (var property in declaringType.GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance))
if (property.IsDefined(typeof(XmlIgnoreAttribute), false))
var propertyItemType = property.PropertyType.GetListType();
if (propertyItemType == null)
if (propertyItemType == itemType)
attributes = new XmlAttributes();
foreach (var derivedType in derivedTypes)
attributes.XmlArrayItems.Add(new XmlArrayItemAttribute { Type = derivedType });
if (itemType.IsConcreteType())
attributes.XmlArrayItems.Add(new XmlArrayItemAttribute { Type = itemType });
overrides.Add(declaringType, property.Name, attributes);
public static class TypeExtensions
public static bool IsConcreteType(this Type type)
return !type.IsAbstract && !type.IsInterface;
public static Type GetListType(this Type type)
var genType = type.GetGenericTypeDefinition();
if (genType == typeof(List<>))
return type.GetGenericArguments()[0];
public static void Test()
var root = new RootObject
SerializedListObjects = new List<A> { new B(), new C() },
var serializer = AListSerializerFactory.Instance.CreateSerializer(root.GetType());
var xml = root.GetXml(serializer);
var root2 = xml.LoadFromXml<RootObject>(serializer);
var xml2 = root2.GetXml(serializer);
Assert.IsTrue(root2.AList.SerializedListObjects.Select(a => a.GetType()).SequenceEqual(root.AList.SerializedListObjects.Select(a => a.GetType())));
Assert.IsTrue(XNode.DeepEquals(XElement.Parse(xml), XElement.Parse(xml2)));
static void TestComplexRoot()
var root = new ComplexRootObject
MidObject = new MidObjectDerived
DerivedSerializedListObjects = new List<A> { new A(), new B(), new C(), new D() },
AnotherSerializedListObjects = new List<A> { new A(), new B(), new C(), new D() },
SerializedListObjects = new List<A> { new A(), new B(), new C(), new D() },
var serializer = ComplexAListSerializerFactory.Instance.CreateSerializer(root.GetType());
var xml = root.GetXml(serializer);
var root2 = xml.LoadFromXml<ComplexRootObject>(serializer);
var xml2 = root2.GetXml(serializer);
Assert.IsTrue(XNode.DeepEquals(XElement.Parse(xml), XElement.Parse(xml2)));
public static class ComplexAListSerializerFactory
static readonly XmlArrayItemTypeOverrideSerializerFactory instance;
static ComplexAListSerializerFactory()
var declaringTypeList = new[]
typeof(ComplexRootObject),
typeof(MidObjectDerived),
var derivedTypesList = new Dictionary<Type, Func<IEnumerable<Type>>>
{ typeof(A), () => new [] { typeof(B), typeof(C), typeof(D) } },
instance = new XmlArrayItemTypeOverrideSerializerFactory(declaringTypeList, derivedTypesList);
public static IXmlSerializerFactory Instance { get { return instance; } }
public static class XmlSerializationHelper
public static T LoadFromXml<T>(this string xmlString, XmlSerializer serial = null)
serial = serial ?? new XmlSerializer(typeof(T));
using (var reader = new StringReader(xmlString))
return (T)serial.Deserialize(reader);
public static string GetXml<T>(this T obj, XmlSerializer serializer = null)
using (var textWriter = new StringWriter())
var settings = new XmlWriterSettings() { Indent = true };
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
(serializer ?? new XmlSerializer(obj.GetType())).Serialize(xmlWriter, obj);
return textWriter.ToString();
public class AssertionFailedException : System.Exception
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
public static class Assert
public static void IsTrue(bool value)
public static void IsTrue(bool value, string message)
throw new AssertionFailedException(message ?? "failed");
public static void Main()
Console.WriteLine("Roslyn 2.0 Compiler; Environment version: " + Environment.Version);
Console.WriteLine("Uncaught exception: ");