Reflect POCO Data as Key-Value Pairs using RouteValueDictionary

Although the developers of the RouteValueDictionary class (available since .NET Framework 3.5 SP1) may not have exactly envisioned the following general usage scenario for the class, it provides a convenient way to indirectly reflect over the properties of an object (such as a POCO entity) and extract the data as a basic key-value-set by simply calling one of the class constructors. The following C# console application illustrates how to use the constructor for this purpose and displays the key-value pairs of two examples as XML.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Routing;
using System.Xml.Linq;
 
namespace TiaanDotCom.Samples.Reflection.RouteValueDictionaryDemo
{
    class Program
    {
        static XElement GetObjectAsXml(
            string rootElementName, object simpleDataObject)
        {
            // Extract property values of object (reflection indirectly)
            IDictionary<string, object> keyValueSet =
                new RouteValueDictionary(simpleDataObject);
 
            // Convert key-value set into XML
            return new XElement(
                rootElementName ?? simpleDataObject.GetType().Name, 
                    keyValueSet.Select(@item => 
                        new XElement(@item.Key, @item.Value)));
        }
 
        static void Main(string[] args)
        {
            // Illustrate concepts through some examples
            Console.WriteLine("<!-- Example 1: Well-defined type -->");
            Console.WriteLine(GetObjectAsXml(null,
                DateTime.Parse("2009-03-16")));
            Console.WriteLine();
            Console.WriteLine("<!-- Example 2: Anonymous type -->");
            Console.WriteLine(GetObjectAsXml("root", new {
                x = 123, 
                y = "Hello world", 
                z = new XElement[] { 
                    new XElement("a", null), 
                    new XElement("b", DateTime.MaxValue) } }));
        }
    }
}

The console output of the program is as follows:

<!-- Example 1: Well-defined type -->
<DateTime>
<Date>2009-03-16T00:00:00</Date>
<Day>16</Day>
<DayOfWeek>Monday</DayOfWeek>
<DayOfYear>75</DayOfYear>
<Hour>0</Hour>
<Kind>Unspecified</Kind>
<Millisecond>0</Millisecond>
<Minute>0</Minute>
<Month>3</Month>
<Second>0</Second>
<Ticks>633727584000000000</Ticks>
<TimeOfDay>PT0S</TimeOfDay>
<Year>2009</Year>
</DateTime>
 
<!-- Example 2: Anonymous type -->
<root>
<x>123</x>
<y>Hello world</y>
<z>
<a />
<b>9999-12-31T23:59:59.9999999</b>
</z>
</root>

The first example involves an instance of a well-defined type, namely the built-in System.DateTime type that has a couple of properties to make this contrived application more interesting. The second example shows that this mechanism can also be used with anonymous types, and it further illustrates an interesting special case where the property named z contains an XML value itself (resulting in sub-elements for the output).

Download: Program.cs (1.45 KB)