<?xml version="1.0" encoding="UTF-8"?>
<code>
  <code>	public class XmlStringSerializer
	{
		static Dictionary&lt;string, Type&gt; types = new Dictionary&lt;string, Type&gt;();
		public string Serialize(object o)
		{
			StringBuilder sb = new StringBuilder();
			Type t = o.GetType();
			if (t.IsSerializable)
			{
				XmlSerializer serializer = new XmlSerializer(t);
				using (TextWriter tw = new StringWriter(sb))
				{
					var namespaces = new XmlSerializerNamespaces();
					namespaces.Add("", "");
					serializer.Serialize(tw, o, namespaces);
					tw.Close();
				}
			}
			else
			{
				throw new InvalidOperationException(string.Format("Objects of type {0} are not serializable.", t.Name));
			}
			sb.Remove(0, 42);
			sb.Insert(0, '.');
			sb.Insert(0, t.Namespace);
			sb.Insert(0, '&lt;');
			return sb.ToString();

		}


		public T DeSerializeObject&lt;T&gt;(string content)
		{
			var typeName = content.Substring(1, content.IndexOf(' ', 20) - 1);
			Type type;
			if (!types.ContainsKey(typeName))
			{
				type = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a =&gt; a.GetTypes()).Single(t =&gt; t.FullName == typeName);
				lock (types)
				{
					types[typeName] = type;
				}
			}
			else
			{
				type = types[typeName];
			}
			object o;
			var serializer = new XmlSerializer(type);
			int posAfterTypeName = content.IndexOf(' ');
			int posOfStartOfTypeName = content.LastIndexOf('.', posAfterTypeName) + 1;

			content = @"&lt;?xml version=""1.0"" encoding=""utf-16""?&gt;&lt;" + content.Substring(posOfStartOfTypeName);
			using (TextReader tr = new StringReader(content))
			{
				o = serializer.Deserialize(tr);
				tr.Close();
			}
			return (T) o;
		}
	}</code>
  <comment>The default XML serializer does some things I consider undesirable
1. The XML it produces is full of unnecessary XML Namespace stuff
2. It is not polymorphic - say you have class B : A { }, and have serialized a type B, you should be able to call Deserialize&lt;A&gt;() on it

My implementation corrects these issues, but it seems a bit crazy!

</comment>
  <created-at type="datetime">2009-01-22T01:04:59+00:00</created-at>
  <id type="integer">710</id>
  <language>C#</language>
  <permalink>polymorphic-xml-serializer</permalink>
  <refactors-count type="integer">3</refactors-count>
  <title>Polymorphic XML serializer</title>
  <trackback-url></trackback-url>
  <updated-at type="datetime">2009-02-08T16:50:06+00:00</updated-at>
  <user-id type="integer">1282</user-id>
  <refactors type="array">
    <refactor>
      <code>using System;
using System.IO;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    public class Program
    {
        static void Main(string[] args)
        {
            // Serialize a Person object and deserialize it back to a Person or an Employee
            string SerializedObject = SerializedObject = CustomSerializer.Serialize(new Person() { Id = 1, FirstName = "Peter", LastName = "Pan" });
            Person oPerson = CustomSerializer.DeSerialize&lt;Person&gt;(SerializedObject);
            Employee oEmployee = CustomSerializer.DeSerialize&lt;Employee&gt;(SerializedObject);
            
            // At this point the Employee.Title is empty, everything's normal. Then we will
            // serialize the same Employee object and deserialize it back to a Person object
            oEmployee.Title = "Hero";            
            SerializedObject = CustomSerializer.Serialize(oEmployee);
            oPerson = CustomSerializer.DeSerialize&lt;Person&gt;(SerializedObject);

            Console.ReadLine();
        }
    }

    /// &lt;summary&gt;
    /// Contains information about a person.
    /// &lt;/summary&gt;
    /// &lt;remarks&gt;
    /// The XmlRoot attribute allow to serialize a Person object 
    /// and to deserialize it back to a Person or an Employee 
    /// object without "manipulating" the xml string.
    /// &lt;/remarks&gt;
    [Serializable, XmlRoot("Base")]
    public class Person
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    /// &lt;summary&gt;
    /// Contains information about an employee.
    /// &lt;/summary&gt;
    /// &lt;remarks&gt;
    /// The XmlRoot attribute allow to serialize a Person object 
    /// and to deserialize it back to a Person or an Employee 
    /// object without "manipulating" the xml string.
    /// &lt;/remarks&gt;
    [Serializable, XmlRoot("Base")]
    public class Employee : Person
    {
        public string Title { get; set; }
    }

    /// &lt;summary&gt;
    /// 
    /// &lt;/summary&gt;
    public class CustomSerializer
    {
        /// &lt;summary&gt;
        /// Serialize an object to xml
        /// &lt;/summary&gt;
        /// &lt;param name="pSource"&gt;Object Type&lt;/param&gt;
        /// &lt;returns&gt;String&lt;/returns&gt;
        public static string Serialize(object pSource)
        {
            // Normally I'd use this 4 lines but since you need cleaner xml see below
            //StringWriter oWriter = new StringWriter();
            //XmlSerializer oSerializer = new XmlSerializer(pSource.GetType());
            //oSerializer.Serialize(oWriter, pSource);
            //return oWriter.ToString();

            XmlSerializerNamespaces oNamespaces = new XmlSerializerNamespaces();
            oNamespaces.Add("", "");

            StringWriter oWriter = new StringWriter();
            XmlSerializer oSerializer = new XmlSerializer(pSource.GetType());
            oSerializer.Serialize(oWriter, pSource, oNamespaces);

            string Serialized = oWriter.ToString();
            return Serialized.Remove(0, Serialized.IndexOf('&lt;', 1));
        }

        /// &lt;summary&gt;
        /// Deserialize an xml string to an object
        /// &lt;/summary&gt;
        /// &lt;param name="pXmlSource"&gt;Xml Source&lt;/param&gt;
        /// &lt;returns&gt;Deserialized object&lt;/returns&gt;
        public static T DeSerialize&lt;T&gt;(string pXmlSource)
        {
            return (T)(new XmlSerializer(typeof(T)).Deserialize(new StringReader(pXmlSource)));
        }
    }
}</code>
      <code-id type="integer">710</code-id>
      <comment>Unfortunately, your code wasn't working for me. I think that my default xml encoding differs from yours so that your hard-coded string manipulation isn&#8217;t working properly. On the other side, I worked on a cleaner way to achieve what you want. It can serializes an object of type A, then deserializes it back to the same type or to an object of type B : A like you mentioned. The key of the implementation is to use a general root name (see XmlRoot in my code) for both objects. Enough talking, see the code below :)</comment>
      <created-at type="datetime">2009-01-22T03:45:27+00:00</created-at>
      <id type="integer">144121</id>
      <language>C#</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Polymorphic XML serializer</title>
      <user-id type="integer">1025</user-id>
      <user-name>Moonshield</user-name>
      <user-website>www.analystik.ca</user-website>
    </refactor>
    <refactor>
      <code>using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using NUnit.Framework;

namespace XmlSerializerTests
{
	namespace XmlSerializerTests.SomeOtherNamespace
	{
		[Serializable]
		public class Person
		{
			public int Id { get; set; }
			public string FirstName { get; set; }
			public string LastName { get; set; }

		}
	}
	[Serializable]
	public class Person
	{
		public int Id { get; set; }
		public string FirstName { get; set; }
		public string LastName { get; set; }
		
	}

	[Serializable]
	public class Employee : Person
	{
		public string Title { get; set; }
	}

	[TestFixture]
	public class Tests
	{
		CustomSerializer serializer = new CustomSerializer();
		[Test]
		public void TestThatAClassCanBeDeserializedAsItsBaseClass()
		{
			var employee = new Employee() {FirstName = "John", LastName = "Doe", Id = 1, Title = "Dogsbody"};
			var xml = serializer.Serialize(employee);
			var obj = serializer.DeSerializeObject&lt;Person&gt;(xml);
			Assert.AreEqual(typeof (Employee), obj.GetType());
		}
		[Test, ExpectedException(typeof(InvalidCastException))]
		public void NoDuckSerializationTest()
		{
			var person = new Person() { FirstName = "John", LastName = "Doe", Id = 1};
			var xml = serializer.Serialize(person);
			var someOtherPerson = serializer.DeSerializeObject&lt;XmlSerializerTests.SomeOtherNamespace.Person&gt;(xml);
		}
		
	}

	public class CustomSerializer
	{
		static Dictionary&lt;string, Type&gt; types = new Dictionary&lt;string, Type&gt;();
		public string Serialize(object o)
		{
			StringBuilder sb = new StringBuilder();
			Type t = o.GetType();
			if (t.IsSerializable)
			{
				XmlSerializer serializer = new XmlSerializer(t);
				using (TextWriter tw = new StringWriter(sb))
				{
					var namespaces = new XmlSerializerNamespaces();
					namespaces.Add("", "");
					serializer.Serialize(tw, o, namespaces);
					tw.Close();
				}
			}
			else
			{
				throw new InvalidOperationException(string.Format("Objects of type {0} are not serializable.", t.Name));
			}
			sb.Remove(0, 42);
			sb.Insert(0, '.');
			sb.Insert(0, t.Namespace);
			sb.Insert(0, '&lt;');
			sb.Remove(sb.Length - t.Name.Length - 2, t.Name.Length + 2);
			sb.Append(t.FullName);
			sb.Append(@"/&gt;");
			return sb.ToString();

		}


		public T DeSerializeObject&lt;T&gt;(string content)
		{
			var indexOfFirstSpace = content.IndexOf(' ', 20);
			var indexOfFirstBreak = content.IndexOf("\r\n");
			var indexOfFirstCloseBrace = content.IndexOf("&gt;");
			var endOfTypeNameIndex = new[] {indexOfFirstSpace, indexOfFirstBreak, indexOfFirstCloseBrace}.Where(i =&gt; i &gt; -1).Min();

			var typeName = content.Substring(1, endOfTypeNameIndex - 1).Trim();
			Type type;
			if (!types.ContainsKey(typeName))
			{
				type = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a =&gt; a.GetTypes()).Single(t =&gt; t.FullName == typeName);
				lock (types)
				{
					types[typeName] = type;
				}
			}
			else
			{
				type = types[typeName];
			}
			object o;
			var serializer = new XmlSerializer(type);
			int posAfterTypeName = content.IndexOf(' ');
			int posOfStartOfTypeName = content.LastIndexOf('.', posAfterTypeName) + 1;

			content = @"&lt;?xml version=""1.0"" encoding=""utf-16""?&gt;&lt;" + content.Substring(posOfStartOfTypeName);
			content = content.Substring(0, content.Length - typeName.Length - 2) + '/' + type.Name + '&gt;';
			using (TextReader tr = new StringReader(content))
			{
				o = serializer.Deserialize(tr);
				tr.Close();
			}
			return (T)o;
		}

	}
}</code>
      <code-id type="integer">710</code-id>
      <comment>Good effort but I'm afraid it doesn't quite fit the bill of what I'm looking for (I should have been a bit clearer about the requirements)! I actually need to have the object B returned as type B, even though it is stored in a field reference of type A. I've rewritten my code so it a/ should work better and b/ has a unit tests. The tests should stay the same</comment>
      <created-at type="datetime">2009-01-22T10:28:59+00:00</created-at>
      <id type="integer">144183</id>
      <language>C#</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Polymorphic XML serializer</title>
      <user-id type="integer">1282</user-id>
      <user-name>mcintyre321</user-name>
      <user-website nil="true"></user-website>
    </refactor>
    <refactor>
      <code></code>
      <code-id type="integer">710</code-id>
      <comment>Have you looked at the DataContractSerializer class?</comment>
      <created-at type="datetime">2009-02-08T16:50:04+00:00</created-at>
      <id type="integer">146386</id>
      <language>C#</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Polymorphic XML serializer</title>
      <user-id type="integer">1277</user-id>
      <user-name>Ants</user-name>
      <user-website nil="true"></user-website>
    </refactor>
  </refactors>
</code>
