Wednesday, November 25, 2009

C# 4.0 – Learning About Dynamic Objects

When I first read about dynamic objects earlier this year, I must admit, I wasn’t sure how much use they would be to me other then, for example, COM programming. Now, considering that I currently do no COM development at all, this left me feeling that dynamic objects was never going to be useful in my arsenal of development tools. Well, that’s what I thought…until now.

Last week at the PDC 09 there was a session given about the new language features of C#/VB.NET in .NET 4.0, and from what I’ve watched so far, I’m excited at the possibilities. After watching the part about dynamic objects, I decided to have a go at a simple prototype app that shows how they can be used. Check out his class:

  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Dynamic;
  4.  
  5. namespace Dynamic_Test
  6. {
  7.     class MyDynamicObject : DynamicObject
  8.     {
  9.         IEnumerable<string> _data;
  10.         IEnumerable<string> _headers;
  11.  
  12.         public MyDynamicObject(IEnumerable<string> headers, IEnumerable<string> data)
  13.         {
  14.             this._headers = headers;
  15.             this._data = data;
  16.         }
  17.  
  18.         public override bool TryGetMember(GetMemberBinder binder, out object result)
  19.         {
  20.             result = _data.ElementAt(_headers.ToList().FindIndex(s => s == binder.Name));
  21.  
  22.             return true;
  23.         }
  24.     }
  25. }

Here I have a class that inherits from DynamicObject and overrides the TryGetMember. Doesn’t look like anything special yet, I’m just getting started. Now, here is my console app that makes use of the above class:

  1. using System;
  2. using System.Collections.Generic;
  3.  
  4. namespace Dynamic_Test
  5. {
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             List<string> headers = new List<string>();
  11.             List<string> data = new List<string>();
  12.  
  13.             headers.Add("Test");
  14.             headers.Add("Another column");
  15.  
  16.             data.Add("Value of item 1");
  17.             data.Add("Value of item 2");
  18.  
  19.             dynamic line = new MyDynamicObject(headers, data);
  20.  
  21.             Console.WriteLine(line.Test);
  22.         }
  23.     }
  24. }

Before I explain how the code works, have a look at line 21. Notice how I reference the ‘Test’ property on the object instance of MyDynamicObject – bear in mind that MyDynamicObject  doesn't have a ‘Test’ property, but the code still compiles without error. How so? Well, by declaring object ‘line’ to be of type dynamic, the compiler will treat this as something which will be sorted out at runtime – it’s not the compiler’s problem if 'property ‘Test’ doesn’t exist during a build. :)

When running the above code, you’ll see that the magic happens when you hit the line:

Console.WriteLine(line.Test);


The code will enter the TryGetMember method of MyDynamicObject. In that method I have an expression that searches for the string ‘Test’ in the collection _headers (remember, it’s searching for ‘Test’ since that’s the dynamic property reference by ‘line.Test’). If the string is found in _headers, it’s index is returned to pick out the string in the collection _data. So in our example, the string ‘Test’ is found at element 0 of _headers, and element 0 of _data is ‘Value of item 1’, so that is the string which is displayed in the console window. Elementary stuff, but already very powerful.

In the PDC video, the speaker shows an example of code which reads the contents of a CSV file and by using dynamic objects he can reference dynamic properties to read values from the CSV via their columns. It’s worth checking out.