- | rssFeed | My book on MSBuild and Team Build | Archives and Categories Wednesday, June 04, 2008

DataContract XML Helper

Lately I've been doing some work with WCF and I have had a need to easily convert from object->XML and from XML->object. These XML strings were created using the DataContractSerializer. So I threw together this util class [yeah I know I probably shouldn't have these, but you know you do too J ]. There are really 2 methods GetDataContractXml and BuildFromDataContractXml. The GetDataContractXml returns the XML for the object provided and the BuildFromDataContractXml method will create the object from the XML string. These methods have both a generic and non-generic method. The non-generic versions are particularly useful if you are using this with reflection. Anywayz, the class itself is shown below, and you can download the file at the bottom of this post.

///
/// © Copyright Sayed Ibrahim Hashimi
/// www.sedodream.com
///
using System;
using System.IO;
using System.Xml;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Xml.Serialization;
namespace Sedodream.Sample.Serialization01.Util
{
    public static class XmlUtils
    {
        /// 
        /// Builds an object of the specified type from the given
        /// XML representation that can be passed to the DataContractSerializer
        /// 
        public static object BuildFromDataContractXml(string xml, Type type)
        {
            if (string.IsNullOrEmpty(xml)) {throw new ArgumentNullException("xml"); }
            if (type == null) { throw new ArgumentNullException("type"); }

            object result = null;
            DataContractSerializer dcs = new DataContractSerializer(type);
            using (StringReader reader = new StringReader(xml))
            using (XmlReader xmlReader = new XmlTextReader(reader))
            {
                result = dcs.ReadObject(xmlReader);
            }

            return result;
        }
        /// 
        /// Builds an object from its XML 
        /// representation that can be passed to the DataContractSerializer.
        /// 
        public static T BuildFromDataContractXml(string xml)
        {
            if (string.IsNullOrEmpty(xml)) { throw new ArgumentNullException("xml"); }

            T result = default(T);

            object objResult = BuildFromDataContractXml(xml, typeof(T));
            if (objResult != null)
            {
                result = (T)objResult;
            }
            return result;
        }
        /// 
        /// Gets the XML representation of the given object
        /// by using the DataContracSerializer.
        /// 
        public static string GetDataContractXml(T obj)
        {
            if (obj == null) { throw new ArgumentNullException("obj"); }

            return GetDataContractXml(obj.GetType(), obj);
        }
        /// 
        /// Gets the XML representation of the given object
        /// of specfiied type by using the DataContracSerializer.
        /// 
        public static string GetDataContractXml(Type type, object val)
        {
            if (type == null) { throw new ArgumentNullException("type"); }
            if (val == null) { throw new ArgumentNullException("val"); }

            MemoryStream ms = new MemoryStream();
            string xml = null;
            try
            {
                DataContractSerializer dcs = new DataContractSerializer(type);

                using (XmlTextWriter xmlTextWriter = new XmlTextWriter(ms, System.Text.Encoding.Default))
                {
                    xmlTextWriter.Formatting = System.Xml.Formatting.Indented;
                    dcs.WriteObject(xmlTextWriter, val);
                    xmlTextWriter.Flush();
                    ms = (MemoryStream)xmlTextWriter.BaseStream;
                    ms.Flush();
                    xml = UTF8ByteArrayToString(ms.ToArray());
                }
            }
            finally
            {
                if (ms != null)
                {
                    ms.Close();
                    ms = null;
                }
            }
            return xml;

        }
        /// 
        /// Writes the XML representation from the DataContractSerializer
        /// into the specified filename. If a file at filename
        /// already exists then an Exception will be thrown.
        /// 
        public static void WriteDateContractToFile(string filename, T obj)
        {
            WriteDateContractToFile(filename, obj.GetType(), obj);
        }
        /// 
        /// Writes the XML representation from the DataContractSerializer
        /// into the specified filename. If a file at filename
        /// already exists then an Exception will be thrown.
        /// 
        public static void WriteDateContractToFile(string filename, Type type, object val)
        {
            if (string.IsNullOrEmpty(filename)) { throw new ArgumentNullException("filename"); }
            if (val == null) { throw new ArgumentNullException("val"); }

            if (File.Exists(filename)) { throw new ArgumentException("filname"); }

            //TODO: Stream this into the file instead of this!!!
            File.WriteAllText(filename, GetDataContractXml(type, val));
        }
        private static String UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            string constructedString = encoding.GetString(characters);
            return (constructedString);
        }
        private static Byte[] StringToUTF8ByteArray(String pXmlString)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] byteArray = encoding.GetBytes(pXmlString);
            return byteArray;
        }
    }
}

To show how this can be used here is a quick sample unit test shown below, this will be a part of a later post on a related topic.

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using Sedodream.Sample.Serialization01;
using Sedodream.Sample.Serialization01.Util;

namespace unittest.Sedodream.Sample.Serialization01
{
    [TestFixture]
    public class TestXmlUtils
    {
        [Test]
        public void TestCreateXml()
        {
            string name = "Sayed Ibrahim Hashimi";
            string email = "sayed.hashimi@gmail.com";


            Person person = new Person();
            person.Name = name;
            person.Email = email;

            string xml = XmlUtils.GetDataContractXml(person);
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
            Assert.IsTrue(xml.Contains(name));
            Assert.IsTrue(xml.Contains(email));
        }
        [Test]
        public void TestCreateFromXml()
        {
            const string xml =
@"
  sayed.hashimi@gmail.com
  9891668d-8107-4f3e-85a4-79e941453be2
  Sayed Ibrahim Hashimi
";

            string name = "Sayed Ibrahim Hashimi";
            string email = "sayed.hashimi@gmail.com";
            Guid id = new Guid("9891668d-8107-4f3e-85a4-79e941453be2");

            Person person = XmlUtils.BuildFromDataContractXml(xml);
            Assert.IsNotNull(person);
            Assert.AreEqual(name, person.Name);
            Assert.AreEqual(email, person.Email);
            Assert.AreEqual(id, person.Id);
        }
    }
}

Where the simple Person class is shown here

[DataContract(Namespace="http://schemas.sedodream.com/Serialization/2008/04")]
public class Person
{
    #region Constructors
    public Person()
    {
        Id = Guid.NewGuid();
    }
    #endregion

    [DataMember]
    public string Name
    {
        get;
        set;
    }
    [DataMember]
    public string Email
    {
        get;
        set;
    }
    [DataMember]
    public Guid Id
    {
        get;
        set;
    }
}

From the two simply test you can see how to create the object from the XML string and vice versa. As far as I know these work pretty good, if you find any issues please let me know and I can update them. At some point I will post some more information that is related to this keep an eye for it.

 

XmlUtils.cs

Sayed Ibrahim Hashimi

DataContractSerializer | WCF Wednesday, June 04, 2008 6:54:58 AM (GMT Daylight Time, UTC+01:00)  #     |