Dynamic typing with C#4.0


I’m sure I saw a video of Anders Heijlsberg doing something like this but anyway, I knocked this up in about five minutes and it’s well smart!

This is an example of what you can do in C#4.0 with dynamic:

   1: dynamic bag = new DynamicBag ();

   2:  

   3: // Assign the value "Isaac" to property "Test" on bag, then write it out.

   4: bag.Test = "Isaac";

   5: System.Console.WriteLine (bag.Test);

   6:  

   7: // Create an anonymous type and place into Stuff, then print out the Age

   8: bag.Stuff = new { Name = "Isaac Abraham", Age = 29, City = "London" };

   9: System.Console.WriteLine (bag.Stuff.Age);

What’s cool is that bag has no such property at compile time called Test or Stuff. And even if they did, “Stuff” couldn’t be of the type that gets assigned to it as that type is generated anonymously.

So how do you do this? I was looking through wikipedia on C#4.0, having seen a nice video on Channel 9 on the language, and saw the following sentence:

Dynamic lookup is performed using three distinct mechanisms: COM IDispatch for COM objects, IDynamicObject DLR interface for objects implementing that interface, and Reflection for all other objects. Any C# class can therefore intercept dynamic calls on its instances by implementing IDynamicObject.

So, I opened up VS2010, created a class and tried to inherit from DynamicObject. At first I got nowhere, and couldn’t even find the Microsoft.CSharp assembly to reference, until I realised that for some reason VS2010 had started my project targeting .NET 3.5 instead of 4.0. Having fixed this, I was able to quickly knock up my dynamic property bag class:

   1: class DynamicBag : DynamicObject

   2: {

   3:     Dictionary<string, object> PropertyBag = new Dictionary<string, object> ();

   4:  

   5:     public override bool TrySetMember (SetMemberBinder binder, object value)

   6:     {

   7:         if (PropertyBag.ContainsKey (binder.Name))

   8:             PropertyBag[binder.Name] = value;

   9:         else

  10:             PropertyBag.Add (binder.Name, value);

  11:  

  12:         return true;

  13:     }

  14:  

  15:     public override bool TryGetMember (GetMemberBinder binder, out object result)

  16:     {

  17:         if (PropertyBag.ContainsKey (binder.Name))

  18:         {

  19:             result = PropertyBag[binder.Name];

  20:             return true;

  21:         }

  22:  

  23:         result = null;

  24:         return false;

  25:     }

  26: }

So what happens when we try to access a property on dynamic? Well, my (hugely limited understanding) is that the C# runtime binder first sees if it can resolve the property request itself. If it can’t (as in our case), it then asks the DLR to see if it can do it. So the DLR sees if the object implements DynamicObject, and if it does, it then calls one of the above methods TrySetMember and TryGetMember.

And it just works! I’m still not entirely sure of the times when we should and shouldn’t use this. But it’s quite cool to see nonetheless 🙂

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