Home > .NET > Cool Things to Do with Dynamics in dotNET 4

Cool Things to Do with Dynamics in dotNET 4

Are Extension Methods a Code Smell?

December 21st | 2009

Cool Things to Do with Dynamics in .NET 4.0

In An Overview of C# 4.0 I discussed some of new features in C# 4.0. One thing that I didn’t cover was the dynamic keyword.

Put simply, something marked as dynamic does not have any compile-time enforced semantics. Instead, all members of the instance are resolved at runtime by the Dynamic Language Runtime (DLR). Here is a simple example:

static void Main(string[] args)
{
    dynamic int1 = 1;
    dynamic int2 = 2;
    dynamic result = int1 + int2;
    Console.WriteLine(result);
}

This, as expected, will print 3. However, the operator + and what int1 and int2 really are is resolved at run time. I’ll demonstrate this using the following code (which looks like it shouldn’t compile, but actually does):

static void Main(string[] args)
{
    dynamic int1 = 1;
    dynamic ex1 = new Exception("Oops!");
    dynamic result = int1 + ex1;
    Console.WriteLine(result);
}

This normally wouldn’t compile since an int type and the Exception type do not have a + operator. Regardless, this code compiles just fine. It’s only at runtime that we get an error:

Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Operator ‘+’ cannot be applied to operands of type ‘int’ and ‘System.Exception’

So, what use is this? Why don’t we just use the real types rather than dynamic? Possible scenarios for using dynamic are: when we don’t know what the type is; or when it came from an odd place, such as reflection. If a type is resolved via reflection, we can treat it as a dynamic and not worry about calling “Invoke” or “GetProperty” on it. The same goes with COM Interop. If a complete wrapper is missing then we can declare it as dynamic and continue to use it without significant complex code.

But the most interesting use of a dynamic is declaring your own. Enter the DynamicObject base type. This allows us to tell the object how to behave at run time and instruct it how to handle the resolution of properties and methods. We can build some very powerful tools with this.

I’ve done some neat things with PowerShell, and the thing that particularly amazed me was how easy it is to consume and manipulate XML. Here’s a PowerShell snippet that loads an XML file:

$xmlConfig = New-Object XML

$xmlConfig.Load(“Some XML Path”);

$backup = ($xmlConfig.configuration.appSettings.add | where {$_.key –eq ‘BackupEveryInMinutes’}).value;

This XML file looks something like this:

<configuration>
    <appSettings>
        <add key="BackupEveryInMinutes" value="1440" />
    </appSettings>
</configuration>

$backup will be assigned to 1440. I like the way you can just access the properties off of the $xmlConfig as if they were always there. In C# and .NET previously, this would have been impossible. However, using the DynamicObject, we can build one that does. Let’s start!

Let’s make a class that derives from DynamicObject.

public class DynamicXml : DynamicObject
{
}

An important concept in this is being able to override TryGetMember. This is how we tell the DLR how to dynamically resolve something.

public class DynamicXml : DynamicObject
{
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
    }
}

· binder – this is what is attempting to be bound, or resolved. It can tell us what the DLR is trying to figure out, such as a property name

· result – to tell the DLR the value of what is being resolved.

· return – if the dynamic was successfully resolved. In our case, we will return false if the XML document doesn’t contain a node. This will cause the DLR to throw an exception if the return value is false.

First we must load our XML document. Let’s use an XmlDocument (as opposed to the newer XDocument) as an example. The constructor will take an XmlNode since XmlDocument inherits from XmlNode.

So the usage scenario for our code will be something like this:

XmlDocument document = new XmlDocument();

document.Load(“pathtoxml.xml”);

dynamic dynamicXml = new DynamicXml(document);

string value = dynamicXml.configuration.appSettings.add.value;

The properties being used on the dynamicXml are the nodes of what we are trying to access. We can check the binder to see what property is being resolved. We can recursively return our dynamic object to continue resolution, too. The final result looks like this:

using System.Xml;
using System.Collections.Generic;
using System.Dynamic;

namespace CSharp4
{
    public class DynamicXml : DynamicObject
    {
        private readonly XmlNode _node;

        public DynamicXml(XmlNode node)
        {
            _node = node;
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = null;
            XmlNodeList nodes = _node.SelectNodes(binder.Name);
            if (nodes.Count == 0)
                nodes = _node.SelectNodes("@" + binder.Name); //Check and see if it's an attribute.
            if (nodes.Count == 0)
                return false;
            if (nodes.Count == 1)
            {
                XmlNode node = nodes[0];
                result = GetContent(node);
            }
            else
            {
                List<dynamic> results = new List<dynamic>();
                foreach (XmlNode node in nodes)
                {
                    results.Add(GetContent(node));
                }
            }
            return true;
        }

        private dynamic GetContent(XmlNode node)
        {
            if (node.NodeType == XmlNodeType.Attribute)
                return node.Value;
            if (node.HasChildNodes || node.Attributes.Count > 0)
                return new DynamicXml(node);
            return node.InnerText;
        }

        public override string ToString()
        {
            return this;
        }

        public static implicit operator string(DynamicXml xml)
        {
            return xml._node.InnerText;
        }
    }
}

Sure, it’s not perfect. It could handle collections better instead of returning a list and support for types other than a string. And this isn’t the best solution either. It’s a nice syntax but using the XDocument and LINQ is a better alternative. However I think it’s a great use for dynamics.

Do you agree? Let us know. Based on your feedback, we may include another installment on this subject—with improvements.

Kevin Jones is a Team Lead at Thycotic Software, an agile software services and product development company based in Washington DC. Secret Server is our flagship password management software product. On Twitter? Follow Kevin

Categories: .NET
  1. ksamdev
    December 22, 2009 at 10:44 am

    Funny but dynamic types exist in other languages for years:

    void * in C++
    id in Objective-C
    etc.

  2. December 25, 2009 at 4:49 am

    useful post. Thanks

  3. March 20, 2010 at 1:09 pm

    Another cool thing you can do with the new dynamic type is multiple method dispatch or advanced polymorphism. Take a look at Type Systems Demystified

  4. John
    September 2, 2010 at 4:11 am

    Your formatting is really messed up on this blog post. Cant see the code from Chrome

  5. September 2, 2010 at 3:56 pm

    Hey John – thanks for pointing this out. We had a server crash and migrated the blog to WordPress. In the process our theme was lost. Hope you can see the post now.

  1. December 22, 2009 at 9:45 am
  2. December 23, 2009 at 4:29 am

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

%d bloggers like this: