Solving the “XmlSerializer and ‘not expected’ Inherited Types” problem without implementing IXmlSerializable

Last week I ran into the following exception when serializing an object into xml:

System.InvalidOperationException: There was an error generating the XML document. —>  System.InvalidOperationException: The type <Type> was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.

The business object I was trying to serialize had a similar construction like these classes:

public class FooParent
{
	public Foo MyFoo { get; set; }
	public List<Foo> MyFoos { get; set; }
}

public class Foo
{
	public int X { get; set; }
	public int Y { get; set; }
}

However the Foo members of the FooParent where not set with Foo objects, but with SqlFoo objects derived from Foo and with a class definition in a different assembly:

public class SqlFoo : Foo
{
	public SqlFoo() : this(0) {}

	public SqlFoo(int id)
	{
		this.ID = id;
	}

	public int ID { get; set; }
}

So, the next test example will throw the InvalidOperationException:

FooParent target = new FooParent();
target.MyFoo = new SqlFoo(1);
target.MyFoos = new List<Foo>(new SqlFoo[] { new SqlFoo(2) });

XmlSerializer serializer = new XmlSerializer(typeof(FooParent));
StringWriter writer = new StringWriter();
serializer.Serialize(writer, target);

After consulting my dear friend Dr. Google, I found a nice solution from Simon Hewitt. I really liked the usage of the implicit casting operators! But I didn’t like implementing the IXmlSerializable interface. There is too much thinking involved about XmlAttributeOverrides and XmlReader, and I wishes there would be a more intuitively solution.

Luckily I also had an Epiphany of my own!  I tried this Foo wrapper, which continues the idea of using the casting operators:

public class XmlFooWrapper
{
	private Foo model;

	public XmlFooWrapper() : this(new Foo()) {}

	public XmlFooWrapper(Foo model)
	{
		this.model = model;
	}

	public static implicit operator Foo(XmlFooWrapper wrapper)
	{
		return wrapper != null ? wrapper.model : null;
	}

	public static implicit operator XmlFooWrapper(Foo model)
	{
		return model!= null ? new XmlFooWrapper(model) : null;
	}

	public int X
	{
		get { return model.X; }
		set { model.X = value; }
	}

	public int Y
	{
		get { return model.Y; }
		set { model.Y = value; }
	}
}

The FooParent was altered by adding the [XmlElement(Type = typeof(XmlFooWrapper))] attribute to the MyFoo member. The List<> member was decorated with the [XmlArrayItem(ElementName=“Foo”, Type=typeof(XmlFooWrapper))] attribute:

public class FooParent
{
	[XmlElement(Type = typeof(XmlFooWrapper))]
	public Foo MyFoo { get; set; }

	[XmlArrayItem(ElementName = "Foo", Type = typeof(XmlFooWrapper))]
	public List<Foo> MyFoos { get; set; }
}

It worked! Running the test example again results in the following xml:

<FooParent>
  <MyFoo>
    <X>0</X>
    <Y>0</Y>
  </MyFoo>
  <MyFoos>
    <Foo>
      <X>0</X>
      <Y>0</Y>
    </Foo>
  </MyFoos>
</FooParent>
Advertisements

One Response to Solving the “XmlSerializer and ‘not expected’ Inherited Types” problem without implementing IXmlSerializable

  1. Peter says:

    Very useful, thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: