blogs.conchango.com

welcome to the conchango blogging site
Welcome to blogs.conchango.com Sign in | Join | Help
in Search

Howard van Rooijen's Blog

Generics and Serialization

Roy Osherove has been blogging about Generics a few times 1 2 3 this week - which reminded me that I had a post saved in my “Drafts” folder in Outlook that simply said “talk about Generics and Serialization”.

One of the main benefits of Generics in .NET 2.0 is the ability to reduce code bloat, whether that manifests itself in reducing lines of code containing in boiler plated strongly typed custom collection classes generated by CodeSmith or a Visual Studio macro or the simplified way of implementing IComparable<T> over IComparable or IBindingList<T> over the nearly incomprehensible IBindingList.

My favourite use of generics has to be using it to simplify Serialization; what was once a onerous task can now be templated, put in a helper class and never has to be thought about again. Below is a little example of the above in action. All the code required to (de)serialize has been distilled into the static class (another neat feature of .NET 2.0) Serializer. This class has two methods - CreateInstance<T>(string serializedType) which allows you to create an instance of the specified type from XML and SaveInstance<T>(T t, string fileName)which allows you to save a serialized copy of the object to a file.

Below is a little sample that shows the code in action - the basic intension is create a new Person class, populate it, serialize it to a file, then deserialize it into a second instance of the Person class and then print out the full name. (You can also use this serialization / deserialization technique as a means to implementing a "Deep Copy" for the ICloneable interface.)

namespace Conchango.Generics.Serialization.Demo
{
    using System;
    using System.IO;
    using System.Text;
    using System.Xml;
    using System.Xml.Serialization;

    public class Person
    {
        private string firstName;
        private string lastName;

        public Person() { }

        public Person(string firstName, string lastName)
        {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public string FirstName
        {
            get { return this.firstName; }
            set { this.firstName = value; }
        }

        public string LastName
        {
            get { return this.lastName; }
            set { this.lastName = value; }
        }

        public override string ToString()
        {
            return this.firstName + " " + this.lastName;
        }
    }

    public static class Serializer
    {
        private static object syncRoot = new object();

        public static T CreateInstance<T>(string serializedType) where T : new()
        {
            T customType = new T();

            XmlSerializer serializer = new XmlSerializer(typeof(T));

            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(serializedType);
            XmlNodeReader xmlNodeReader = new XmlNodeReader(xmlDocument);

            try
            {
                customType = (T)serializer.Deserialize(xmlNodeReader);
            }
            catch
            {
                //TODO: Add Logging etc here...
                throw;
            }

            return customType;
        }

        public static void SaveInstance<T>(T t, string fileName) where T : new()
        {
            lock (syncRoot)
            {
                FileInfo fileInfo = new FileInfo(fileName);

                if (!fileInfo.Exists)
                {
                    fileInfo.Directory.Create();
                }

                XmlSerializer serializer = new XmlSerializer(typeof(T));

                using (XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.UTF8))
                {
                    serializer.Serialize(writer, t);
                }
            }
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            string filePath = @"c:\temp\SerializationDemo\p1.xml";

            Person p1 = new Person("Enoch", "Root");

            Serializer.SaveInstance<Person>(p1, filePath);

            Person p2 = Serializer.CreateInstance<Person>(File.ReadAllText(filePath));

            Console.WriteLine(p2.ToString());
            Console.ReadKey();
        }
    }
}

I've used the CreateInstace<T>() method in two projects I've already blogged about - Windows Workflow: Congestion Charge Demo and Team Foundation Server Notification Web Services: Visual Studio 2005 Project Template and numerous other hobby projects. For the Congestion Charge Demo, I use CreateInstance<T>() to stub out the data access layer in the TFS Notification Web Services I use CreateInstance<T>() (in the EndpointBase class) to deserialize the incoming notification message into CLR type for further manipulation. 

Published 21 May 2006 17:06 by howard.vanrooijen
Filed under: , ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

No Comments

Leave a Comment

(required) 
(optional)
(required) 
Submit
Powered by Community Server (Personal Edition), by Telligent Systems