Wednesday 17 August 2011

The Dynamic Landscape

 

The ‘dynamic’ keyword is new to C# 4.0.

 

The DLR is a major new feature of the language that changed the way we can do API’s and interface with dynamic languages forever.

 

In this article I will show you what is available and briefly touch on scenarios you may use it.

 

Any object may be declared as dynamic and will automatically become late-bound:

dynamic i = 1;
Console.WriteLine(i + 1);

image

Consider a method that takes in a dynamic variable:

image

Declaring the parameter as dynamic causes code completion to tell us that it will only be evaluated at run-time (late-bound).

Suppose our consumer method takes a dynamic object and tries to call the Hello method as follows:

void Consumer(dynamic worldObject)
{
    Console.WriteLine(worldObject.Hello());
}

We can pass in any object to this function and it will compile and run fine as long as by the time it is executed the worldObject has the method Hello().

We can declare any object and add this method:

class ConcreteObject
{
    public string Hello()
    {
       return "Hello";
    }
}
Consumer(new ConcreteObject());
image

ExpandoObject

With ExpandoObject we can create any object with any method or property we want at runtime:

dynamic dyn = new ExpandoObject();

We can add the method as follows:

Func<string> hello = () => "Hello";

dyn.Hello = hello;
Consumer(dyn);

Prints the same result:

image

DynamicObject

Is what we would use if we want even more control over a method or property as it is evaluated. It provides virtual methods that can be overwritten each time someone tries to call a method or read a member.

We can create a DynamicObject and create our own ExpandoObject:

class MyDynamicObject : DynamicObject
{
  Dictionary<string, dynamic> _members;
  public MyDynamicObject ()
  {
      _members = new Dictionary<string, dynamic>();
  }
  public void AddMember<T>(string name, T member)
  {
      _members[name] = member;
  }

  public override bool TryGetMember(GetMemberBinder binder, out object result)
  {
     result = _members[binder.Name];
     return true;
  }
  public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
  {
      var member = _members[binder.Name];
      Delegate del = (Delegate)member;
      result = del.DynamicInvoke(args);
      return true;
  }
}
We can then use it this way:
var myDynamicWrapper = new MyDynamicObject();
myDynamicWrapper.AddMember<Func<string>>("Hello", () => "Hello");
dynamic dyn = myDynamicWrapper;
Consumer(dyn);

And again we get this output:

image

Why

As the main point was not to try and tell you why you should care I think there are a few ideas to think about. The ‘dynamic’ wherever it comes up in conversation will certainly be a point of controversy, much more than when the ‘var’ keyword when it was introduced.

There are many articles where people debate this like this one.

"Static when possible; dynamic when necessary."

You may think you will never use this, and maybe all coding should be statically typed but if you are using Javascript you are writing dynamic code already!

Even though C# 4.0 introduced this feature for supporting dynamic languages doesn’t mean we can never use this.

Here are some scenarios you may want to consider using it (feel free to leave your comments if you can think of more)

Dynamic instead of reflection

Dynamic is far easier/cleaner and the compiler generates more efficient IL code than using reflection.

COM/APIs

Wherever you do not have concrete static interfaces and objects are only known at runtime this is the obvious choice.

HTML/XML

If you need to implement a DOM and had to look up nodes when you don’t have a statically generated schema.

Patterns

One pattern that comes to mind is the visitor. This is a hard pattern to implement in C# due to all the plumbing required and often the pattern itself is overly complicated for simple solutions. Creating a dynamic object and using the Expando for example we can create visitors and only implement the methods we are interested in.

Testing

Even though we can use dynamic proxies to easily test objects we could not easily, for instance testing private methods. I feel that this is not the real power. In dynamic programming every object can be replaced by another (a mock). This is not possible in a static language.

Final thoughts

There is a good chance you may not need to write dynamic code. Most people feel that static programming is more reliable because the compiler checks for errors.

I say the dynamic language’s biggest flaw can be its greatest strength if you consider from a testing perspective all dynamic code can be easily unit tested where static code can not always. Then I heard Scott Hanselman use the phrase: Some Duck Typing pragmatists say:

“The compiler is just another unit test”

So next time you write Javascript code spare a thought for the dynamic programming you are doing.