Thursday, April 28, 2011

Doing the dynamic thing (Part IV)

This is already the fourth part in this series (for the full story, see posts 1, 2 and 3). And as promised, I'm going to do something a bit more advanced in this post. I will introduce you to the ExpandoObject and, in a fifth post, the DynamicObject classes. They bring you new opportunities for dynamically expanding your code, hence the term EXPANDOObject. Something you can, for instance also do in dynamic languages like Ruby (in one of the next posts I will show you some IronRuby code).

The ExpandoObject can be found in de System.Dynamic namespace (system.core.dll) and is actually a kind of key value set of keys (names) and implementations for these keys. These implementations can be fields, methods, properties, delegates, ... The funky thing is, you can add these implementations at runtime. You can start of with an ExpandoObject with no functionality at all and you can add functionality as you go.  The following line of code gives you an empty ExpandoObject:
dynamic sampleObject = new ExpandoObject();

Adding a property is as simple as:
sampleObject.test = "Dynamic Property"; //I now have a property 'test'
Console.WriteLine(sampleObject.test);
Console.WriteLine(sampleObject.test.GetType());

You can also add methods at runtime:
sampleObject.number = 10;
sampleObject.Increment = (Action)(() => { sampleObject.number++; });

// Before calling the Increment method.
Console.WriteLine(sampleObject.number);

sampleObject.Increment();

// After calling the Increment method.
Console.WriteLine(sampleObject.number);

This will print 10 and 11 to the console respectively.
It is also possible to add events at runtime:
sampleObject.sampleEvent = null;

// Add an event handler.
sampleObject.sampleEvent += new EventHandler(SampleHandler);

// Raise an event for testing purposes.
sampleObject.sampleEvent(sampleObject, new EventArgs());

Besides this dynamically adding of functionality, the ExpandoObject is actually nothing more than a fancy key value set. It actually implements the IDictionary interface, which means you can enumerate all members you have just added.
Console.WriteLine("sampleobject: ");
foreach (var property in (IDictionary<String, Object>)sampleObject)
{
    Console.WriteLine(property.Key + ": " + property.Value);
}
        }

        // Event handler.
        static void SampleHandler(object sender, EventArgs e)
        {
            Console.WriteLine("SampleHandler for {0} event", sender);
        }
    }
}
The above program will give you the following output:

Now, this is where most examples on ExpandoObject stop. It explains the use of the class, and that's it. On the other hand, this is where I start thinking, ok, cool, but what's the use? I mean, how can I use this dynamic run time behaviour in my everyday coding life. For this, in my opinion, the ExpandoObject runs a little short. The fact that an ExpandoObject is actually nothing more than a fancy dictionary means you can also add functionality through this dictionary, but this is a little pain staking, so I will not go into this. You will, however, get more practical use out of the DynamicObject class, which I will explain in the next post on this subject.

No comments:

Post a Comment