Xml serializing immutable objects

If you are familiar with Domain Driven Design concepts, you probably know what a Value Object is. For those who don’t, Value Objects are objects, that describe things but have no identity, as opposed to Entities. It is also recommended that Value Object are immutable, which means that they are created with constructors and never modified, which means they only have getter properties.

That ruins it all if you need to serialize your object to xml using XmlSerializer, since it requires the classes you want to serialize to have public getters and setters.

If you try to serialize a class like this:

public class Address
{
	public Address(string city, string street, int house)
	{
		this.City = city;
		this.Street = street;
		this.HouseNumber = house;
	}

	public string City
	{
		get;
		private set;
	}

	public string Street
	{
		get;
		private set;
	}

	public int HouseNumber
	{
		get;
		private set;
	}
}

which matches the definition of Value Object, you will get InvalidOperationException saying that some (or all) of the properties are read-only.

How to solve it without exposing setter properties? Implement IXmlSerializable interface! It requires you to implement three methods:

public class Address: IXmlSerializable
{
	private Address()
	{
	}

	public Address(string city, string street, int house)
	{
		this.City = city;
		this.Street = street;
		this.HouseNumber = house;
	}

	public string City
	{
		get;
		private set;
	}

	public string Street
	{
		get;
		private set;
	}

	public int HouseNumber
	{
		get;
		private set;
	}

	#region IXmlSerializable Members

	public System.Xml.Schema.XmlSchema GetSchema()
	{
		return null;
	}

	public void ReadXml(System.Xml.XmlReader reader)
	{
		this.City = reader.ReadElementString();
		this.Street = reader.ReadElementString();
		this.HouseNumber = int.Parse(reader.ReadElementString());
	}

	public void WriteXml(System.Xml.XmlWriter writer)
	{
		writer.WriteElementString("City", this.City);
		writer.WriteElementString("Street", this.Street);
		writer.WriteElementString("HouseNumber", this.HouseNumber.ToString());
	}

	#endregion
}

You can control the way xml is written out. Also notice the private parameterless constructor – it is also a requirement of XmlSerializer (it requires a parameterless constructor, it can have any access modifier, but we use private, since we only want objects created with the main constructor, where you pass the values in). You may also want to implement IXmlSerializable explicitly, to keep your class interface clean.

I believe it’s not very fancy, but it does get the job done without violating Value Object definition. I’d be interested to see any other ways to implement this too, since I failed to find anything useful on internet. 🙂

Advertisements

2 thoughts on “Xml serializing immutable objects

  1. Hello,

    In my program I needed to have members with private setters to be serialized by the webservice. I found your article and decided to try it.

    I found two problems when replicating the code. I created a test project with a webservice, a Person class and a consumer project to consume the webservice.

    The first problem I encountered was that the webservice needs the parameterless constructor to be public. Any other type of visibility resolved in an error.

    The second problem I had was when I changed the parameterless constructor to public and consumed the webservice in my test app. The result came back as a DataSet and not as the serialized object. On this site: http://support.microsoft.com/kb/815131 Microsoft reports it as a bug and says you can fix it in the generated proxy. But I don’t like that because the proxy changes every time you update the webservice. Besides that, the custom class which implements IXmlSerializable is not available in the proxy as well.

    I know your article is not about webservices, but perhaps you can indicate what I should be doing differently to make your code work with webservices.

    Kind regards,

    Michel van der Weide

  2. Hello,

    I’ve not found any decent solution to serializing IXmlSerializable objects for web services. All I found was that it’s a bad idea to use IXmlSerializable with web services.

    I think I would go with Data Transfer Objects in this case. These are dumb containers that only contain data from original object (Person class instance in your example) and no methods. It would have public getters and setters and parameterless constructor, as XmlSerializer needs.

    So when you want to transmit a Person over web service, you create a DTO from it’s data (PersonDTO) and return it. On the client side, a Person should then be created from PersonDTO, or ,if the data needs to only be shown, you can use the DTO directly.

    You can read much more about DTOs by googling if you need 🙂

    OR, another option is to write your own proxy generator. I think I’ve seen some on the web.

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