Welcome to MSDN Blogs Sign in | Join | Help
Fun with Anonymous Types and LINQ to XML

(August 2, 2008: This post uses the wrong approach.  I've written a new post that shows the way to accomplish the same thing in the functional style.) 

You can, of course, use C# anonymous types to create types that are more than simple tuples. For example, you can nest anonymous types to create an object graph:

var PurchaseOrder = new {
    PurchaseOrderNumber = "99503",
    OrderDate = DateTime.Parse("1999-10-20"),
    Addresses = new [] {
        new {
            AddressType = "Shipping",
            Name = "Alice Smith",
            Street = "123 Maple Street",
            City = "Mill Valley",
            State = "CA",
            Zip = "90952",
            Country = "USA"
        },
        new {
            AddressType = "Billing",
            Name = "Robert Smith",
            Street = "8 Oak Avenue",
            City = "Old Town",
            State = "PA",
            Zip = "95819",
            Country = "USA",
        }
    },
    Comment = "Hurry, my lawn is going wild",
    Items = new [] {
        new {
            PartNumber = "872-AA",
            ProductName = "Lawnmower",
            Quantity = 1,
            USPrice = 148.95,
            Comment = "Confirm this is electric",
            ShipDate = DateTime.MinValue
        },
        new {
            PartNumber = "926-AA",
            ProductName = "Baby Monitor",
            Quantity = 2,
            USPrice = 39.98,
            Comment = (string)null,
            ShipDate = DateTime.Parse("1999-05-21")
        }
    }
};

This also has applicability with LINQ to XML. For example, you can use a small method that uses reflection to populate an XML tree. The following looks for public properties in the type and iterates over them, creating XElement objects. If a property implements the IEnumerable interface, then the method uses recursion to iterate over the children of the property.

static void ObjectGraphToXElement(XElement parent, object o) {
    MemberInfo[] members =
        o.GetType().GetMembers(BindingFlags.Public |
                               BindingFlags.Instance);
    foreach (MemberInfo m in members) {
        PropertyInfo p = m as PropertyInfo;
        if (p != null) {
            Type t = p.PropertyType;
            object val = p.GetValue(o, null);
            if (val != null) {
                if (t.IsValueType || t == typeof(string))
                    parent.Add(new XElement(m.Name, val));
                else {
                    XElement newParent = new XElement(m.Name);
                    parent.Add(newParent);
                    foreach (var v in (val as IEnumerable))
                        ObjectGraphToXElement(newParent, v);
                }
            }
        }
    }
}

The following code uses ObjectGraphToXElement to create an XML tree:

XElement po = new XElement("PurchaseOrder");
ObjectGraphToXElement(po, PurchaseOrder);
Console.WriteLine(po);

When run, it produces the following output:

<PurchaseOrder>
  <PurchaseOrderNumber>99503</PurchaseOrderNumber>
  <OrderDate>1999-10-20T00:00:00</OrderDate>
  <Addresses>
    <AddressType>Shipping</AddressType>
    <Name>Alice Smith</Name>
    <Street>123 Maple Street</Street>
    <City>Mill Valley</City>
    <State>CA</State>
    <Zip>90952</Zip>
    <Country>USA</Country>
    <AddressType>Billing</AddressType>
    <Name>Robert Smith</Name>
    <Street>8 Oak Avenue</Street>
    <City>Old Town</City>
    <State>PA</State>
    <Zip>95819</Zip>
    <Country>USA</Country>
  </Addresses>
  <Comment>Hurry, my lawn is going wild</Comment>
  <Items>
    <PartNumber>872-AA</PartNumber>
    <ProductName>Lawnmower</ProductName>
    <Quantity>1</Quantity>
    <USPrice>148.95</USPrice>
    <Comment>Confirm this is electric</Comment>
    <ShipDate>0001-01-01T00:00:00</ShipDate>
    <PartNumber>926-AA</PartNumber>
    <ProductName>Baby Monitor</ProductName>
    <Quantity>2</Quantity>
    <USPrice>39.98</USPrice>
    <ShipDate>1999-05-21T00:00:00</ShipDate>
  </Items>
</PurchaseOrder>

Pretty cool, eh?

Posted: Saturday, September 16, 2006 7:13 PM by EricWhite
Filed under: ,

Comments

Eric White's Blog said:

Just as soon as I learn something, I blog it. This has a potential pitfall – sometimes I blog something

# August 2, 2008 7:52 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

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

Page view tracker