Saturday, December 12, 2009

.NET 4.0 and VS 2010 Series – Dynamic Features

Technorati Tags: ,,,,

I have deliberately delayed writing this post to try and get my heads around all the dynamic features in .NET 4.0. At first read, I thought it was just the Expando object and whenever you use the ExpandoObject in your code, the code runs in DLR. Though this is partly true, I realised there is a bit more to the dynamic features than just a two-liner.

The Dynamic Features are implemented in the following forms in .NET 4.0

  • The Expando Object
  • The Dynamic Object
  • The Dynamic Language Runtime (DLR)

ExpandoObject

As the name roughly suggests, expandos are expandable objects which means you can add properties, methods and even events at runtime. You can also set and get the values of such members.

The syntax to create expandable objects is as follows

dynamic person = new ExpandoObject();
person.FirstName = "test First Name";
person.LastName = "test Last Name";

You will see that I have created the person object as dynamic. We will come to that a bit more later. If you compile a solution, with just this piece of code, it will compile perfectly fine.

You can also pass Expando objects as parameters to other methods or functions. Beware that when you do so, you will not get intellisense on the dynamic object because they aren’t yet resolved; they are resolved only during runtime. Below is a code snippet where I have created an ExpandoObject and passed that as a parameter to another method that displays the values of the object’s. members.

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Dynamic;
   6:  
   7:  
   8: namespace DLRExample
   9: {
  10:     class Program
  11:     {
  12:         static void Main(string[] args)
  13:         {
  14:  
  15:             dynamic Vehicle = new ExpandoObject();
  16:             Vehicle.Make = "Ford";
  17:             Vehicle.Model = "Endeavour";
  18:             Vehicle.Engine = "4 cylinder";
  19:             Vehicle.Color = "Black";
  20:  
  21:             WriteVehicleDetails(Vehicle);
  22:             Console.ReadLine();
  23:         }
  24:  
  25:  
  26:         static void WriteVehicleDetails(dynamic vehicleobject)
  27:         {
  28:             Console.WriteLine("The make of the vehicle is {0}", vehicleobject.Make);
  29:             Console.WriteLine("The color of the vehicle is {0}", vehicleobject.Color);
  30:         }
  31:     }
  32: }

Similarly, .NET allows you to add methods at runtime to an expando object. In C#, you can add methods by using lambda expressions. The syntax for the same is as below

expandObject.Increment = (Action)(() => { expandoObject.attribute++; });

I have modified the above code to add a method to the ExpandoObject called ChangeVehicleColor. The method changes the color of the vehicle to white from its existing value. The new code is as below


   1: using System;
2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Dynamic;
   6:  
   7:  
   8: namespace DLRExample
   9: {
  10:     class Program
  11:     {
  12:         static void Main(string[] args)
  13:         {
  14:  
  15:             dynamic Vehicle = new ExpandoObject();
  16:             Vehicle.Make = "Ford";
  17:             Vehicle.Model = "Endeavour";
  18:             Vehicle.Engine = "4 cylinder";
  19:             Vehicle.Color = "Black";
  20:             Vehicle.ChangeVehicleColor = (Action)(() => {Vehicle.Color="White";});
  21:             WriteVehicleDetails(Vehicle);
  22:             Vehicle.ChangeVehicleColor();
  23:             WriteVehicleDetails(Vehicle);
  24:             Console.ReadLine();
  25:         }
  26:  
  27:  
  28:         static void WriteVehicleDetails(dynamic vehicleobject)
  29:         {
  30:             Console.WriteLine("The make of the vehicle is {0}", vehicleobject.Make);
  31:             Console.WriteLine("The color of the vehicle is {0}", vehicleobject.Color);
  32:         }
  33:     }
  34: }


Please note that the syntax to invoke the method in C# is slightly different from VB.NET. In VB.NET, you will have to use the Invoke function explicitly to call the dynamic method.

Lastly, the expando object also implements the generic IDictionary interface. This enables developers to enumerate the members of the object, if need be. The syntax to enumerate the members is fairly simple. For the vehicle object above, the code will be as below

foreach (var property in (IDictionary<String, Object>)Vehicle)

{

Console.WriteLine(property.Key + ": " + property.Value);

}


Dynamic Object

The dynamic object has been introduced in C# for a variety of reasons. One of the most important aspects of the dynamic object is that it skips type checking during compile time. You can invoke any method on the dynamic object type without having to worry about compiling errors.

Thought at the outset, the dynamic and expando objects seem similar, there are a number of differences between the two. While you can instantiate an expandoobject class, you cannot do the same with a dynamic class. Dynamic object is just a holding class. They are declared with the dynamic keyword as shown in my first example in this post.

Some of the practical usages of the dynamic object are with COM Interops. Instead of trying to tightly bind an interop class you can always declare that class as dynamic. You will do away with a lot of type casting that needs to be done otherwise.

Dynamic Language Runtime (DLR)

The DLR is an open source runtime that sits above the CLR and ensures the working of the dynamic languages in .NET. Apart from the two objects described above, .NET also supports a couple of dynamic languages like IronRuby and IronPython. These run on the DLR. You can download the latest version of DLR from codeplex.

What the DLR does is to keep track of usages of the dynamic objects and ensures that they are evaluated at runtime. For this, the DLR has three services


  • Expression Trees - These represent language syntaxes and semantics

  • Call Site Caching – These help track dynamic object usages and information about operations on the Dynamic Objects

  • Dynamic Object Interoperability – These are essentially a set of interfaces that help creation of dynamic objects.

You can get more information about the DLR here.

Usage Scenarios

Now that we have seen the different elements of dynamic features in C# 4.0, let me try and explain where I think these can be used.


  • The Expando object is interoperable between different framework languages. So it is an obvious choice in situations where you have to pass objects between different framework languages.

  • String to object conversion scenarios. A scenario commonly found in projects where mainframe is involved. I think it would be compelling to use the Expando object along with text generation templates to come up with a code generator for mapping mainframe strings to application objects

  • As mentioned earlier in the post, the dynamic object is a good choice for interacting with COM interops. Not only that, I think it is very useful to also be used with scripting objects.

  • If these two objects don’t do the trick for you, remember you can always create your own dynamic objects by implementing the IDynamicMetaObjectProvider interface.

That concludes this post regarding the dynamic features in C# 4.0. I hope this has given you a good overview for you to start exploring these objects in a bit more detail