Dynamic typing in C#, challenges with the ExpandoObject
and how to create your own dynamic type
The .NET run-time (CLR) has a dynamic extension the Dynamic Language Runtime built on top of it. This nice feature can be used to implement dynamic languages, like ruby and python on the CLR. This also gives you the option to use dynamic typing in static CLR languages like C#. For the declaration of a dynamic type there is the dynamic keyword, so for example:
dynamic myDynamicVariable = GetSomething();
dynamic myInteger = 1;
A big difference is that all checks are done runtime instead of compile time. The myDynamicVariable is now a completely dynamic type in the DLR extension of the runtime. But how to create a dynamic object in a static language? There the ExpandoObject comes into play, this is basically a Dictionary (Hash-table) that inherits from the DynamicObject type, which has explicit methods for accessor and method resolving. Great! So now I can do this:
dynamic myDynamicThingy = new ExpandoObject();
myDynamicThingy.IntProperty = 1;
But what doesn't work is this:
//throws NullReferenceException
myDynamicThingy.MyOtherProperty.MyNestedProperty = "Yay!";
The above gives a null reference error at runtime since the MyOtherProperty was not initialized.
The way to do this with an ExpandoObject is:
myDynamicThingy.MyOtherProperty = new ExpandoObject();
myDynamicThingy.MyOtherProperty.MyNestedProperty = "Yay!";
This works!
I was working on a simple dsl in c# for a testing framework proof of concept. This required that I could deserialize a Json configuration file that had no schema and could have as much nested items as you liked. When I used the ExpandoObject to create the configuration or to deserialize the configuration I would get null reference errors. This was the case because the properties where not explicitly initialized. I also noticed that the usage of the ExpandoObject did not have a 'dynamic' feel to it. It felt to rigid, you have to do a lot of declarations and 'newing'.
So I created a DynamicObjectDictionary. A staticly typed dynamic class (is that even possible?) that inherits from the DynamicObject like the ExpandoObject does. When you access a property that does not exists it automatically creates a new DynamicObjectDictionary for that property. This means nesting is easy now. The type can be casted easily from and to the ExpandoObject. The casting feature is very helpful since a lot of serialization libraries and frameworks that use dynamic typing, use ExpandoObjects under the hood.
So the dynamic can be used this way:
dynamic myDynamicObject = new DynamicObjectDictionary();
myDynamicObject.CreateMe.MeToo = "Nice work!";
string result = myDynamicObject.CreateMe.MeToo;
//result == "Nice work!"
The full source code is listed below. If you want to see how serialization and dynamic typing is used in an example project look at this project on github.