Serializing data quickly and easily

Have you ever had a class with a bunch of data in it that you needed to store easily in a file or database field? Serialization is usually the easiest answer. But, what should it be serialized to?

The best answers are usually XML or JSON. I prefer XML in most cases since is natively supported by the .NET framework since the early 1.1 days. But serializing data back and forth is an annoying task in most cases so I found an easier way of doing it. By deriving your classes from a special templated base type, you can add serialization to almost any class you create.

I based my class on the The System.Xml.Serialization classes in .NET which can handle the serializing of almost anything. I think the only structure they can’t handle is hash tables or dictionaries. The serializer in WCF does handle those, but there is a performance hit with using that library. The native XML serialization routines can do over 100,000 objects in a second in my experience!

You can also add attributes to your properties and fields to assign specific names to the XML tags if you need to get data in and out of other systems.

You can serialize deep object structures as well. Native types will serialize automatically, and it will attempt to serialize all the public properties an fields of any other object types you use. It’s best though if you have manually added some XML serialization attributes where needed. Deriving from the same XmlBaseType class is also helpful since you can directly serialize any lower portion of your object tree then too.

I’ll start with my base type class. At its minimum, there is the class and two methods defined. One to serialize, the other to deserialize.

[cclne_csharp width=”800″] [Serializable] public class XmlBaseType {
public string Serialize();
public static T Deserialize(string xml);
}

[/cclne_csharp]

The first thing you need to do when you have your data class instance full of data is to serialize it. This Serialize method gets added to every class you create that is inherited from the XmlBaseType class.

[cclne_csharp width=”800″] public string Serialize() {
XmlSerializer serializer = new XmlSerializer(this.GetType());
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add(“”, “”); // Removes namespace crap from xml

using (StringWriter stream = new StringWriter()) {
serializer.Serialize(stream, this, names);
stream.Flush();
return stream.ToString();
}
}
[/cclne_csharp]

Next is the Deserialize method. Given any string with XML information in it, you can call this static Deserialize method on your class file and it will return a new instance of your class with the information loaded.

[cclne_csharp width=”800″] public static T Deserialize(string xml) {
if (string.IsNullOrEmpty(xml)) {
throw new ArgumentNullException(“xml”);
}

XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringReader stream = new StringReader(xml)) {
try {
return (T)serializer.Deserialize(stream);
} catch (Exception ex) {
// The serialization error messages are cryptic at best.
// Give a hint at what happened
if (ex.InnerException != null)
throw new InvalidOperationException(“Failed to ” +
“create object from xml string”, ex.InnerException);
else
throw new InvalidOperationException(“Failed to ” +
“create object from xml string”, ex);

}
}
}

[/cclne_csharp]

So, how about an example of how the class is used. I will create a class derived from the XmlBaseType class, fill it with data, serialize it an then load it into a new instance.

[cclne_csharp width=”800″ lines=”-1″] using System.Xml.Serialization;

public class TestClass : XmlBaseType {
public string FirstName {get; set; }
public string LastName {get; set; }

[XmlElement(“is-a-coder”)] public bool IsACoder {get; set; }

public int TestField = 5;

[XmlArray(“stufflist”, XmlArrayItem(“stuff”,typeof(string))] public List ListOfStuff {get; set; }

public TestClass() {
FirstName = LastName = “”;
IsACoder = false;
ListOfStuff = new List();
}
}

public class Program {
public static void Main(string[] args) {
TestClass test1 = new TestClass() {
FirstName = “Joe”,
LastName = “Bob”,
IsACoder = true,
TestField = 15
};
test1.ListOfStuff.Add(“hello world”);

string xml = test1.Serialize();

TestClass test2 = TestClass.Deserialize(xml);
}
}

[/cclne_csharp]

Of course, once you get the serialized XML from an object, you can do anything with it. Store it in files, databases, compress it, encrypt it, transmit it, etc. All the XmlSerialization attributes can be used on the class properties. It will serialize all public properties and fields automatically unless you override with the serialization attributes.

The class in my library has other methods for loading and saving from files in a variety of ways and even of encrypting the content using my CryptoHelper class (which I’ll discuss later).

Future Direction
I may look at turning these into extension methods on the “object” class itself. That would make it easier to serialize any object in an application. The downside is that I think extensions are a messy hack in most cases. Altering a class that was never intended to have certain functionality is just rude. And it makes following code a lot harder down the line since you don’t know if a class originally had that method, or if not, where the heck it was defined in a very large source tree of code.

This entry was posted in Dennis-IT Tools and tagged , , . Bookmark the permalink.