Monday, September 20, 2010

C# Serialization problem

The core of the messaging program I am working on right now involves messages being encapsulated in XML. C# makes it really easy with their System.XML.Serialization classes. You just have to create a class, populate it, and feed it into :
XmlSerializer serializer
Then by running the Serialize() command you can turn it into XML data. Simple! Of course there's lots of customisation you can do with it, and then it becomes a powerful tool. However, this entry is not discussing the basics, just do a web search for it and you can find 100 of great examples.

My problem came from serializing my message classes. I had one base class, with lots of inherited classes. The very first time I ran either serialize() or deserialize() in my program, it would take up to 15 seconds to complete. But only for the first serialize/deserialize. Every subsequent one was quick.

A bit of research showed that C# builds up assemblies for the XML at runtime, only when needed. With the inheritance of my multiple classes, there was a lot of reflection and recursion done to build the assembly. And since I had it in my startup, my program would take 15 seconds to start up! Not acceptable.

It turns out there is a way to precompile these custom serialization assemblies, but it requires the construction of an additional DLL.

Since .Net 2.0, Microsoft has included a little executable in it's SDK to do it. It's in the SDK folder, so it may be different to my examples on your computer. The program is called SGen. It looks into any of your assemblies and builds up the serialization assemblies required. To use it, run the following command:
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 tools\sgen.exe" /f /v /a:
The flags are:
  1. /f = forces a rewrite of the file
  2. /v = verbose output, it's handy for figuring out problems with the serialisation
  3. /a: = the file to assemble the serialization assembly from. Replace with your .exe or .dll file.
Running this will create a a file with the assembly name followed by .XmlSerialisers.dll. Just place this DLL into the executable folder and it will load automatically on startup. On runtime, the program automatically checks for this file and no longer has to waste my 15 seconds compiling the serialisation data!

If you want to be tricky, move it into your post-build command: