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;
[XmlInclude(typeof(WindowsDevice))]
[XmlInclude(typeof(AndroidDevice))]
public abstract class Device
public class WindowsDevice: Device
public class AndroidDevice: Device
public static class DeviceExtensions
public static string SerializeDevice<TDevice>(this TDevice o) where TDevice : Device
if (!typeof(Device).GetCustomAttributes<XmlIncludeAttribute>().Any(a => a.Type == o.GetType()))
throw new InvalidOperationException("Unknown device type " + o.GetType());
var serializer = new XmlSerializer(typeof(Device));
using (var stringWriter = new StringWriterWithEncoding(Encoding.UTF8))
serializer.Serialize(stringWriter, o);
return stringWriter.ToString();
public static Device DeserializeDevice(this string xml)
var serial = new XmlSerializer(typeof(Device));
using (var reader = new StringReader(xml))
return (Device)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.SerializeDevice();
var test2 = xml.DeserializeDevice();
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; }