Article purpose
The purpose of this article is to explore the implementation of object Xml serialization by means of a single extension method supporting generic types.
Sample source code
This article is accompanied by a sample source code Visual Studio project which is available for download here.
Example custom data type
The sample source code provided with this article provides a user defined data type, the CustomDataType class of which the code snippet is listed below.
public class CustomDataType
{
private int intMember = 0;
public int IntMember
{
get { return intMember; }
set { intMember = value ; }
}
private string stringMember = String.Empty;
public string StringMember
{
get { return stringMember; }
set { stringMember = value ; }
}
private DateTime dateTimeMember = DateTime.MinValue;
public DateTime DateTimeMember
{
get { return dateTimeMember; }
set { dateTimeMember = value ; }
}
}
This article’s accompanying sample source code was implemented to serialize an object instance of type CustomDataType. The resulting Xml markup representation is listed below.
<?xml version= "1.0" encoding="utf-16"?>
<CustomDataType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd= "http://www.w3.org/2001/XMLSchema">
<IntMember>42</IntMember>
<StringMember>Some random string</StringMember>
<DateTimeMember>2013-02-03T17:01:32.9799772+02:00</DateTimeMember>
</CustomDataType>
The serialization method – Implementation as an extension method with generic type support
Extension method architecture enables developers to create methods which, from a syntactic and implementation point of view appear to be part of an existing data type. Extension methods create the perception of being updates or additions, literarily extending a data type as the name implies. Extension methods do not require access to the source code of the particular types being extended, nor does the implementation thereof require recompilation of the referenced types.
This article illustrates a combined implementation of extension methods extending the functionality of generic types. The following code snippet provides the extension method definition.
public static class ExtObject
{
public static string XmlSerialize<T>(this T objectToSerialize)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof (T));
StringWriter stringWriter = new StringWriter ();
XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
xmlWriter.Formatting = Formatting.Indented;
xmlSerializer.Serialize(xmlWriter, objectToSerialize);
return stringWriter.ToString();
}
}
The XmlSerialize method satisfies the requirements of the extension method architecture by being defined as a static method, implemented as a member method of a statically defined class. In addition the method signature features the this keyword preceding all other method parameters. The seemingly contradicting statement of specifying the this keyword in a static context usually serves as a quick indication that a method is implemented as an extension method. Remember that the this keyword provides a reference to the current instance, whereas in the case of static methods and classes there is no current instance, being static results in limiting a type to only one instance accessed as a shared reference.
The definition of the XmlSerialize method also specifies the definition of a generic type <T>. When defining an extension method the first parameter specified indicates the type being extended. As an example, if an extension method definition specifies as a first parameter a variable of type string, the extension method will operate as an extension to the String class. Notice that extending a native value type is possible as a result of .net’s boxing and unboxing functionality.
The XmlSerialize method defines as a first parameter a variable of generic type <T>. Extending a generic type allows the implementing code access to the XmlSerialize method as a member of all data types, except static types. It is not possible to extend a static type.
The implementation
The XmlSerialize method discussed in the previous section appears as a member method to all non static types, provided that the implementing code applies the relevant namespace resolution by specifying the using statement where needed.
static void Main(string [] args)
{
CustomDataType objectInstance = new CustomDataType();
objectInstance.DateTimeMember = DateTime.Now;
objectInstance.IntMember = 42;
objectInstance.StringMember = "Some random string";
string xmlString = objectInstance.XmlSerialize();
Console.WriteLine(xmlString);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Press any key..." );
Console.ReadKey();
}
From the code listed above the XmlSerialize method appears as a member of the CustomDataType class but in reality CustomDataType does not define the XmlSerialize method. The type being extended functions as per normal, not being aware of the extension method XmlSerialize.
The extension method now provides a uniform implementation enabling objects to be serialized to an Xml string, regardless of type.
Note: Not all types can be serialized! A commonly repeated mistake regarding object Xml serialization being that serialization will fail if a type does not provide a constructor with no parameters.