I Am Not Myself

Bills.Pay(Developer.Skills).ShouldBeTrue()

An Exploration of Dynamic in .NET 4

In my spare time I have been working on a Simple.Data provider for Sqlite. Simple.Data is a lightweight ORM written by Mark Rendle that leans heavily on dynamic types and metaprogramming techniques to create an api that is the closest to Ruby’s Active Record that I have ever seen in .NET. I have been using this project as a way to explore the new dynamic features introduced into C# and .NET with version 4. I have discovered some interesting things and wanted to share them.

Before we dive too deeply into dynamic and metaprogramming, let’s explore the evolution of typing in .NET and and it’s impact on how we write C#, the IDE and our wrists. Consider the following program.

using System;

namespace ExploringDynamic
{
    public class ASimpleType
    {
        string someProperty;
        public string SomeProperty
        {
            get { return someProperty; }
            set { someProperty = value; }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ASimpleType item = new ASimpleType();
            item.SomeProperty = "Explicitly Typed";
            Console.WriteLine(item.SomeProperty);
            Console.ReadKey();
        }
    }
}

This simple program represents the prototypical .NET application and is the reason I have carpel tunnel syndrome. It will easily run under any version of the .NET framework and will compile using any version of the C# compiler. We start with a simple class definition that defines the type ASimpleType. The class has a field and a getter and setter for that field exposed as the property SomeProperty. The program creates an instance of the type, sets the property SomeProperty’s value to “Explicitly Typed” and then writes the value to the console using the property. This form of C# is very explicit and verbose and is the form we as .NET developers are most familiar.

using System;

namespace ExploringDynamic
{
    public class ASimpleType
    {
        public string SomeProperty { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var item = new ASimpleType { SomeProperty = "Implicitly Typed" };
            Console.WriteLine(item.SomeProperty);
            Console.ReadKey();
        }
    }
}

With .NET 3.5 came the introduction of the .NET 2.0 runtime and compilers for C#. The compiler added several new language features demonstrated above. The type has been greatly simplified by using Auto Properties. Object creation has changed with the introduction of the var keyword and the use of object initializer syntax. Even though we have introduced several new language features into the program, we can compile this application targeting the .NET 1.1 runtime and it will be functionally equivalent to the original program. These features are for the most part syntactical sugar provided to us by the compiler which is making implicit typing decisions for us.

Update: Looks like I got my history a bit mixed up. Take a look at the insightful comments for further details. With that said the evolution of the language features described here still holds true. It is the versions of the runtimes and frameworks, I got a bit wrong.

This concept can be pushed further with .NET 3.5.

using System;

namespace ExploringDynamic
{
    class Program
    {
        static void Main(string[] args)
        {
            var item = new { SomeProperty = "Anonymously Typed" };
            Console.WriteLine(item.SomeProperty);
            Console.ReadKey();
        }
    }
}

We have now completely removed the need for the class definition by using Anonymous typing. At compile time the compiler will examine this code and generate a type for us to represent the anonymous type. This program can still be compiled targeting the .NET 1.1 runtime and is functionally equivalent to the original program. Anonymous typing does have its limitations.

using System;

namespace ExploringDynamic
{
    class Program
    {
        static void Main(string[] args)
        {
            var item = GetType();
            Console.WriteLine(item.SomeProperty);
            Console.ReadKey();
        }

        static object GetType()
        {
            return new { SomeProperty = "Anonymously Typed" };
        }
    }
}

This program will not even compile. The properties implicitly defined on our anonymous object are only available for use within the scope of the definition of the anonymous object. We can return the anonymous object from the GetType method only as object, so the implicitly typed item variable only has the properties and methods of object available. We will get a compile time error related to the use of the SomeProperty property with any version of the C# compiler.

With the introduction of the dynamic features of .NET 4, can get around this limitation.

using System;

namespace ExploringDynamic
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic item = GetType();
            Console.WriteLine(item.SomeProperty);
            Console.ReadKey();
        }

        static dynamic GetType()
        {
            return new { SomeProperty = "Anonymously Typed" };
        }
    }
}

In this sample, we have simply changed the return type of the GetType method to dynamic. This adds a dependency on the .NET 4 runtime and compilers. The program will compile and run as expected, but we have fundamentally changed the program.

In the previous, versions the compiler was running several type based checks on our code to ensure type safety. The compiler would throw an error if it could not match a property or method to the type we declared a variable. With this version the dynamic keyword is explicitly telling the compiler to not bother with those checks. We could modify line 10 to look like the following code and the compiler would happily accept it.

Console.WriteLine(item.ZippityDoDah);

This causes the program to crash at runtime with a RuntimeBinderException. This exception gives us some insight into another fundamental change introduced into the program. By using the dynamic keyword we have told the compiler to include the use of the Dynamic Language Runtime in the executable.

When the program runs and the runtime encounters a dynamic variable, the DLR is invoked to attempt to resolve the the members of the variable. In the program, the type that is returned by by the GetType method is still a static type, it’s an anonymous type but a type none the less.

Consider the following modification to the program.

using System;

namespace ExploringDynamic
{
    class Program
    {
        public class ASimpleType
        {
            public virtual string SomeProperty { get; set; }
        }

        static void Main(string[] args)
        {
            var item = GetType();
            var item2 = (ASimpleType) item;
            Console.WriteLine(item2.SomeProperty);
            Console.ReadKey();
        }

        static dynamic GetType()
        {
            return new ASimpleType { SomeProperty = "Explictily Typed" };
        }
    }
}

In this example, we have returned to the explicit ASimpleType type and are returning it from our GetType method as a dynamic reference. We can simply cast the reference to the explicit type and carry on as normal. So the dynamic keyword word simply allows the compiler to ignore types at compile time, but dynamic variables can easily reference static types.

One language feature introduced in .NET 3.5 that has not been mentioned yet is extension methods.

using System;

namespace ExploringDynamic
{
    public class ASimpleType
    {
        public virtual string SomeProperty { get; set; }
    }

    public static class Extensions
    {
        public static string GetProperty(this ASimpleType item)
        {
            return item.SomeProperty;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var item = GetType();

            Console.WriteLine(item.GetProperty());
            Console.ReadKey();
        }

        static dynamic GetType()
        {
            return new ASimpleType { SomeProperty = "Explictily Typed" };
        }
    }
}

Based on what we have covered so far, what do you think should happen here? Surprisingly, when we run this version of the program we will get a RuntimeBinderException again. Extension methods are a compiler trick, to make it look like a static type has the extension method in the IDE. Once it is compiled, it is actually a static method call. I can make this program work at runtime by simply casting the return value of the GetType method to the explicit type.

 var item = (ASimpleType) GetType();

Up to this point we have simply played with the dynamic keyword in relation to statically typed objects. The dynamic keyword was introduced to allow us to interact with truly dynamic types. But what is a dynamic type and how do I create one?

A common gateway to dynamic objects is the ExpandoObject class.

using System;
using System.Dynamic;

namespace ExploringDynamic
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic item = new ExpandoObject();
            item.SomeProperty = "Dynamic Object";
            item.GetProperty = (Func<string>) (() => item.SomeProperty);

            Console.WriteLine(item.SomeProperty);
            Console.WriteLine(item.GetProperty());

            item.GetProperty = "BOOOOOOM! Mind BLOWN!";

            Console.WriteLine(item.GetProperty);
            Console.ReadKey();
        }
    }
}

Let that sink in for a second. Look closely at what appears to be going on there. Feel free to visit the MSDN documentation for ExpandoObject and look for the definition of SomeProperty or GetProperty. Notice that I am defining GetProperty as a Func and calling it like a method in one section of code then reassigning it a string value and using it like a property in another section of code.

This is a dynamic object. There is no compiler baby sitting the source code to ensure type integrity. We are free to redefine anything we want on the object. Some people call dynamic typing duck typing, as in “If it walks like a duck and quacks like a duck it must be a duck.”

The ExpandoObject provides canned functionality for mapping members and functions dynamically. But we can implement our own dynamic objects with custom functionality.

using System;
using System.Dynamic;

namespace ExploringDynamic
{
    class Program
    {
        public class ConsoleTalker : DynamicObject
        {
            public override bool TryInvokeMember(InvokeMemberBinder binder,
                                                 object[] args,
                                                 out object result)
            {
                var name = binder.Name;

                if(name.StartsWith("Say"))
                    Console.WriteLine(name.Substring(3) + "!");
                else
                    Console.WriteLine("I don't understand.");

                result = true;
                return true;
            }

            public void SayWorld()
            {
                Console.WriteLine("Universe! Woot.");
            }
        }

        static void Main(string[] args)
        {
            dynamic item = new ConsoleTalker();

            item.SayHi();
            item.SayWorld();
            item.WhisperBoo();

            Console.ReadKey();
        }
    }
}

This introduces metaprogramming into the simple application. The ConsoleTalker class overrides the TryInvokeMember method of DynamicObject. When I invoke a method on an instance of this object, the DLR will attempt to execute the method directly, so calls to the SayWorld method prints “Universe! Woot.” to the console.

If the method is not found, it will call the TryInvokeMember method in an attempt to handle the unknown call. This is very similar to Ruby’s method missing functionality. You can checkout the rest of the API for DynamicObject here.

It is worth nothing here that if I reference the ConsoleTalker explicitly, the compiler kicks in at compile time and will complain about dynamic method and property use. So, while the following is valid it disables dynamic method resolution for all intents and purposes.

var item = new ConsoleTalker();

Even if we use the var keyword, the compiler will assume static typing. We must explicitly use the dynamic keyword.

So what can be accomplished with dynamic and metaprogramming techniques? Consider this program that connects to a Northwind database and prints the name and phone number of all German customers to the console.

public User FindUserByEmail(string email)
using System;
using System.IO;
using System.Reflection;
using Simple.Data;

namespace ExploringDynamic
{
    class Program
    {
        private static readonly string DatabasePath =
            Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),"Northwind.db");

        static void Main(string[] args)
        {
            var db = Database.OpenFile(DatabasePath);
            foreach(var customer in db.Customers.FindAll(db.Customers.Country == "Germany"))
            {
                Console.WriteLine("Customer: {0} Phone: {1}", customer.ContactName, customer.Phone);
            }

            Console.ReadKey();
        }
    }
}

15 responses to “An Exploration of Dynamic in .NET 4

  1. Robin Clowers March 28, 2011 at 2:14 pm

    Shiny new blog, I like it!

    Nice overview of dynamic stuff, very down to earth. Your fourth paragraph makes it sound like the C# 2.0 compiler released with .net 3.5… I believe auto properties are a feature of the C# 3.0 compiler, which shipped with .net 3.5. Of course I could be all washed up 🙂

    • Bobby Johnson March 28, 2011 at 2:17 pm

      You could be right. I was under the impression that 3.0 was all the Windows Foundation stuff, so WPF, WCF & WF. I’ll have to break out my history books and find out.

      • Mark Rendle March 29, 2011 at 3:00 am

        3.0 was the Windows Vista (Avalon/Indigo etc) framework stuff. It still used 2.0 of both the C# compiler and the CLR.

        3.5 (the LINQ release) still ran on v2.0 of the CLR, but came with C# 3.0, which added all the anonymous types, extension methods and so on.

        4.0 is the first version since 2.0 to come with a completely new CLR.

  2. Adron March 28, 2011 at 5:32 pm

    Great post. I’m diggin’ it. …and it reads even better now that it isn’t on a phone display. 😉

  3. Arne Claassen March 29, 2011 at 1:22 pm

    I just wish I could cast a dynamic object to an interface. With the present state of dynamic i need to keep the type dynamic in all signatures, or wrap a proxy around it which is how i did dynamic typing before .NET 4.0 anyhow, i.e. no need for dynamic.

    • Bobby Johnson March 30, 2011 at 7:48 am

      that would be nice, but seems like it would behave oddly considering the way static/dynamic referenced variables work… what if I wanted the interface method to be handled by the try invoke member method, but I have cast it as a interface.. would that work…

  4. Duncan Smart March 30, 2011 at 2:52 am

    Great stuff but some slight historical inaccuracies/version mixups 🙂

    with .NET 3.5 came the introduction of the .NET 2.0 runtime and compilers for C#

    Actually, .NET 3.5 stayed with the .NET 2.0 runtime, but it introduced version 3 of the C# compiler which added new language features such as var, automatic properties, anonymous types, extension methods etc.

    This program can still be compiled targeting the .NET 1.1 runtime

    No, it can target the .NET 2.0 runtime – definitely not the .NET 1.1 runtime.

    See http://en.wikipedia.org/wiki/C_Sharp_(programming_language)

  5. Eric March 30, 2011 at 6:01 am

    I’m compiling some of your examples and I’m running into an issue with the one presenting the ExpandoObject. It seems that my version of Visual Studio 2010 will not compile Line 12:

    item.GetProperty = (Func) (() => item.SomeProperty);

    I am given this error as well:

    Using the generic type ‘System.Func’ requires 1 type arguments

    I really have no idea what I could be missing here to make this work.

  6. Pingback: DotNetShoutout

  7. Pingback: The Morning Brew - Chris Alcock » The Morning Brew #824

  8. Jon Erickson May 11, 2012 at 10:49 am

    another trick we are using is being able to cast a dynamic to a IDictionary and then dynamically adding properties to it just like a statically typed dictionary, we are using this in a ViewModel to “pivot” rows into columns for a grid.

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: