using System.Collections.Generic;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Globalization;
using System.ComponentModel.DataAnnotations;
using System.Collections;
[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class XmlBaseTypeAttribute : System.Attribute
[XmlInclude(typeof(WindowsDevice))]
[XmlInclude(typeof(AndroidDevice))]
public abstract class Device
public class WindowsDevice: Device
public class AndroidDevice: Device
public static class TypeExtensions
public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
public static class XmlExtensions
static Type GetSerializedType(this Type type)
var serializedType = type.BaseTypesAndSelf().Where(t => Attribute.IsDefined(t, typeof(XmlBaseTypeAttribute))).SingleOrDefault();
if (serializedType != null)
if (!serializedType.GetCustomAttributes<XmlIncludeAttribute>().Any(a => a.Type == type))
throw new InvalidOperationException(string.Format("Unknown subtype {0} of type {1}", type, serializedType));
return serializedType ?? type;
public static string Serialize(this object o)
var serializer = new XmlSerializer(o.GetType().GetSerializedType());
using (var stringWriter = new StringWriterWithEncoding(Encoding.UTF8))
serializer.Serialize(stringWriter, o);
return stringWriter.ToString();
public static T Deserialize<T>(this string xml)
var serial = new XmlSerializer(typeof(T).GetSerializedType());
using (var reader = new StringReader(xml))
return (T)serial.Deserialize(reader);
public static void Main()
static void Test<TDevice>() where TDevice : Device, new()
Console.WriteLine("Testing " + typeof(TDevice));
var test = new TDevice();
var xml = test.Serialize();
var test2 = xml.Deserialize<TDevice>();
Assert.IsTrue(test.GetType() == test2.GetType());
Console.WriteLine("Test successful, XML: ");
public class AssertionFailedException : System.Exception
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
public static class Assert
public static void IsTrue(bool value)
throw new AssertionFailedException("failed");
public class StringWriterWithEncoding : StringWriter
private readonly Encoding _encoding;
public StringWriterWithEncoding()
public StringWriterWithEncoding(IFormatProvider formatProvider)
public StringWriterWithEncoding(StringBuilder sb)
public StringWriterWithEncoding(StringBuilder sb, IFormatProvider formatProvider)
: base(sb, formatProvider)
public StringWriterWithEncoding(Encoding encoding)
public StringWriterWithEncoding(IFormatProvider formatProvider, Encoding encoding)
public StringWriterWithEncoding(StringBuilder sb, Encoding encoding)
public StringWriterWithEncoding(StringBuilder sb, IFormatProvider formatProvider, Encoding encoding)
: base(sb, formatProvider)
public override Encoding Encoding
get { return (null == _encoding) ? base.Encoding : _encoding; }