Click here to Skip to main content
13,250,883 members (53,133 online)
Click here to Skip to main content
Add your own
alternative version


11 bookmarked
Posted 5 Jun 2009

C# 4.0: DXLinq, a DynamicObject example

, 5 Jun 2009
Rate this:
Please Sign up or sign in to vote.
System.Xml.Linq is a great library, it lets us very easily manipulate XML, in very close fashion to how we would interact with other data sources. My only issue is that it tends to seem a little redundant...

System.Xml.Linq is a great library, it lets us very easily manipulate XML, in very close fashion to how we would interact with other data sources. My only issue is that it tends to seem a little redundant, given this XML:

  <B X="1"/>
  <B X="2"/>

We would do the following to get the value of both the X attributes:

var root = XElement.Load("Sample.xml");

foreach (var b in root.Elements("B"))

That’s not exactly the cleanest code ever, so what if we could do this instead:

var root = XElement.Load("Sample.xml");

dynamic xml = new DXElement(root);

foreach (var b in xml.B)

Using the combination of C# 4.0’s new dynamic type, and the DynamicObject class, getting this working is actually pretty easy. What we need is a dynamic that will map properties to child elements and attributes. The DynamicObject base class provides an overloadable TryGetMember method that is called whenever the code tries to get a property off of a dynamic. For example, when xml.B is used above, DynamicObject.TryGetMember is called, asking the DynamicObject to return the value of the member. So the DXElement gets to decide what type and value to return, at runtime. Here is my DXElement class, in its entirety:

public class DXElement : DynamicObject
    public XElement BaseElement { get; set; }

    public DXElement(XElement baseElement)
        this.BaseElement = baseElement;

    public override bool TryGetMember(GetMemberBinder binder, out object result)
        //Go ahead and try to fetch all of the elements matching the member name, 
        //and wrap them
        var elements = BaseElement.Elements(binder.Name).Select
			(element => new DXElement(element));

        //Get the count now, so we don't have to call it twice
        int count = elements.Count();
        if (count > 0)
            if (count > 1)
                result = elements; 	//We have more than one matching element, 
				//so let's return the collection
                result = elements.FirstOrDefault(); //There is only one matching element,
					      //so let's just return it

            return true; //return true because we matched
            //Ok, so no elements matched, so lets try attributes
            var attributes = 
		BaseElement.Attributes(binder.Name).Select(attr => attr.Value);
            count = attributes.Count();

            if (count > 0)
                if (count > 1)
                    result = attributes; 	//more than one attribute matched, 
					//let's return the collection
                    result = attributes.FirstOrDefault(); //only one attribute matched, 
							//let's just return it

                return true; // return true because we matched

        //no matches, let's allow the base class to handle this
        return base.TryGetMember(binder, out result);

Not too bad right? Now, it makes a couple of assumptions about the input XML, which are most likely false, but for examples sake, we'll just ignore that fact ;). As you can see, there isn't much code needed, just the TryGetMemeber overload using XLinq against the BaseElement to find what we want to return as the result.


This article, along with any associated source code and files, is licensed under The MIT License


About the Author

Software Developer
United States United States
I currently work as a Software Engineer for a company in North Carolina, mainly working with C#.

You may also be interested in...

Comments and Discussions

GeneralExcel Sheet Pin
kanu@adatapost6-Jun-09 0:43
memberkanu@adatapost6-Jun-09 0:43 
GeneralRe: Excel Sheet Pin
StormySpike7-Jun-09 17:57
memberStormySpike7-Jun-09 17:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.171114.1 | Last Updated 5 Jun 2009
Article Copyright 2009 by StormySpike
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid