Wednesday, November 12, 2008

Using XmlSerializer to serialize type information

During the development of a project I'm currently working on, I ran into this. One property of a class I defined is called SimpleType and it holds a Type object. It contains some basic type like int or string.
Part of the project is to store this information and have it easily configurable, so my first thought was to use the XmlSerializer class to simply serialize the objects inside a collection to an xml file. So I wrote some code to do this:


XmlWriter writer = XmlWriter.Create(@"c:\temp\template.xml");
XmlSerializer serializer = new XmlSerializer(typeof(Template));
serializer.Serialize(writer, template);
writer.Close();


Running this code threw a nice exception: "The type System.Int32 cannot be used in this context". At first I was stunned. I didn't have any properties that even related to int. Then I figured it must be the SimpleType property and I needed some kind of workaround for this behaviour.
Here is the code of the property I tried to serialize:


public Type SimpleType { get; set; }


To make it work I started by adding an XmlIgnore attribute to the SimpleType property. This obviously prevents the serializer from including it into the xml file and stops the error from occurring, but now I had no type information in my xml file and I did need it.
So I added a private field to store the type in and added a second property called SimpleTypeName of type string.
The getter of this property simply returns the SimpleTypes Name property. The setter uses the static Type.GetType method to translate a typename into a Type object and sets it in the field.
Here is the code after I rewrote it:


private Type _simpleType;

[XmlIgnore()]
public Type SimpleType
{
get
{
return _simpleType;
}
set
{
_simpleType = value;
}
}

public string SimpleTypeName
{
get
{
if (_simpleType != null)
{
return _simpleType.Name;
}
else
{
return string.Empty;
}
}
set
{
_simpleType = Type.GetType(value);
}
}


To make this work you obviously need the namespace System.Xml.Serialization.

If you have any questions or remarks, please feel free to comment below.

2 comments:

  1. There's an enumeration you can use for this if you would like to restrict what can be entered in the xml. System.TypeCode

    ReplyDelete
  2. Thanks, kodefuguru. That's a helpful comment. I do want to point out that, altough it limits the options on the type information, it doesn't actualy restrict the options, because you can still have an object as your TypeCode.

    This would in turn mean you would still have to send a classname or something else to identify the type you would want to use. Or you could, very cleanly, exclude this option in code.

    ReplyDelete