Blog - Title

Fun with Anonymous Types and LINQ to XML

Fun with Anonymous Types and LINQ to XML

  • Comments 2

[Blog Map]  This blog is inactive.  New blog: EricWhite.com/blog

(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?

Leave a Comment
  • Please add 6 and 1 and type the answer here:
  • Post
Page 1 of 1 (2 items)