A Nice Use of C# Dynamic

Dynamic capabilities were added to C# 4.0. These capabilities provide the ability to intercept method and property invocations. In certain situations, this is extremely useful, as seen in SignalR.

I’m currently working on an XMPP library which parses a received XMPP Stanza into a class named BvElement. Abstracting from BvElement are classes such as IQ, Message, and Presence.

In a non-dynamic world I have to create properties to represent XML child nodes, or a method which accepts a name and performs the appropriate lookup. This leads to a proliferation of properties, and in most cases this is completely unnecessary – if the node is not present or empty, the consumer will handle that, I just need to return a BvElement representing the node. Where default behavior is expected, for example get is the default type of an IQ stanza, I need a property. But for most purposes, this is not necessary, especially since XMPP is extensible by design.

So instead of writing zillions of properties, using dynamic I am able to achieve code like this, which sets the namespace attribute from a Query element of an IQ:

iq.Query[Xl.Namespace] = Xl.RegisterNamespace;

 
If Query doesn’t exist, an empty element named Query is created and returned. If the Namespace attribute doesn’t exist, an empty attribute named Namespace is created. This greatly simplifies client-side code, there is no need for null testing. It’s pretty much the Null Object Pattern at work.

Dynamic Object

So how does it work? Firstly, I need to inherit from DynamicObject.

public class BvElement : DynamicObject, IEnumerable

Try Get Member

Then I implement the TryGetMember method, which is invoked if a method or property does not exist. In this method I look for the requested element, if it is present I return it, otherwise I add the required element before returning it.

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
    var name = binder.Name;
    var i = IndexOf(name);
    result = i == -1 ? Add(name) : _elements[i];
    return true;
}

Try Set Member

Lastly, I implement the TrySetMember method. Here I am setting the value of an element, creating the element if it doesn’t exist.

public override bool TrySetMember(SetMemberBinder binder, object value)
{
    var name = binder.Name;
    var i = IndexOf(name);

    if (i == -1)
    {
        if (value is BvElement)
        {
            Add(value as BvElement);
        }
        else
        {
            Add(name, Convert.ToString(value));
        }
    }
    else
    {
        if (value is BvElement)
        {
            _elements[i] = (value as BvElement);
        }
        else
        {
            _elements[i].Value = Convert.ToString(value);
        }
    }

    return true;
}

Dynamic

The last piece of the puzzle is the dynamic keyword. You must use this type in order to access the dynamic features:

dynamic iq = myXmppPacket;

 
Now you can use it as mentioned above, i.e. iq.Query[Xl.Namespace]…

Summary

Dynamic is an excellent addition to C#, and surprisingly it performs much faster than reflection. It’s another paradigm for solving problems.

I hope this post helps, you can find the source code for the above class online here.

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s