XML serialization using generics
Posted: February 23rd, 2009 | Author: Michael | Filed under: Uncategorized | No Comments »Generics are one of my favorite bits of C# syntax. They regularly come in handy for making code more elegant and readable. For example, I love using them in applications that do a lot of deserializing, especially if there is anything else (logging, maybe) that I want to be sure of doing at the same time. The method I use looks something like this:
public T Deserialize(string xml) where T : class
{
if (string.IsNullOrEmpty(xml))
throw new ArgumentNullException("xml cannot be null or empty");
XmlSerializer serializer = new XmlSerializer(typeof(T));
T obj;
using (StringReader reader = new StringReader(xml))
{
obj = (T)serializer.Deserialize(reader);
}
_logger.Log(string.Format("Deserialized {0}", obj));
return obj;
}
The T in the angle brackets represents the type of the object that I am trying to deserialize. (It doesn’t have to be the letter T, actually; it can be any valid variable name.) You can restrict the possible types with the where keyword; here, the where T : class after the method declaration specifies that the type must be a class, so if someone tries to use Deserialize, they will get a compiler error. You can also use the T to set the return type, so that the return type of the method can vary. Last but not least, if you are in Boston you can use the T to get from South Station to Harvard Square.
The beauty of this approach is that everything remains strongly-typed. If I deserialize a GolgiApparatus object using Deserialize, the return value will be an GolgiApparatus. There’s no need to identify the object return value as a GolgiApparatus. I can write code like this:
GenericXmlSerializer xml =
new GenericXmlSerializer(new Logger());
GolgiApparatus ga = new GolgiApparatus();
Exception ex = new Exception("you can't do that");
string serializedGolgi = xml.Serialize(ga);
string serializedException = xml.Serialize(ex);
GolgiApparatus reconstitutedApparatus =
xml.Deserialize(serializedGolgi);
In my experience,any time you need to cast a return value from object to some other type,you can clean it up using either a generic method or a generic class.
Incidentally, my Serialize method, which doesn’t need to use generics, usually looks something like this:
public string Serialize(object obj)
{
if (obj == null)
throw new ArgumentNullException("obj cannot be null");
XmlSerializer serializer = new XmlSerializer(obj.GetType());
string xml;
using (StringWriter writer = new StringWriter())
{
serializer.Serialize(writer, obj);
xml = writer.ToString();
}
_logger.Log(string.Format("Serialized {0}", obj.ToString()));
return xml;
}
Leave a Reply