Sunday, 7 February 2016

C# Dynamic Types & Expando Object

Let me get this straight!! You want to declare an Object but you don't know what member variables you need ahead of time. Have you gone mad?

JavaScript Land

You've got to love the dynamic nature of JavaScript and how the language allows you to mutate objects at run-time. You don't need to define class definitions of an object upfront. That's so old-skool!

You can just create them... on the fly!
var movie      = new Object();
movie.name     = "Interstellar";
movie.genre    = "Sci-Fi";
movie.director = "Christopher Nolan";
Later, if you want to add a new member variable or a function at run-time.. Just add it!
movie.Rating = 8;
And of course you could do the same thing using the object literal notation:
var movie2 = {
  name: "Aliens",
  genre:"Action",
  director:"James Cameron"
};
and later:
movie2.Rating = 9;

C# Land

In C# land, things are a little different. A bit more traditional. Our objects need to be declared up front with a class definition. And the blueprint we provide for our classes are very hard to change. I guess they don't call them concrete classes for nothing!.

However, there are times when you would like to have the flexibility of JavaScript in C# and be able to "mutate objects on the fly".

With C# Version 4 that became possible with the dynamic keyword and the ExpandoObject.

Check out this C# code sample below. Its eerily similar to the JavaScript above. The only difference is on the 1st line with the dynamic keyword.
dynamic movie  = new ExpandoObject ();
movie.name     = "Interstellar";
movie.genre    = "Sci-Fi";
movie.director = "Christopher Nolan";
In essence, the dynamic ExpandoObject lets you add (expand) and remove (contract) member properties & functions of an object.

However, if you look at the above code, even though we haven't created a traditional "class definition" for the movie object, the fields are still setup at compile-time. The "name", "genre" and "director" fields are typed into the code at compile-time. Not run-time.

This brings us onto the second cool thing about the ExpandoObject.  It allows you to create an object like above using a dictionary. This means we can dynamically modify an object at run-time, adding or removing properties as required.

For example:

dynamic movie  = new ExpandoObject ();
movie.name     = "Interstellar";
movie.genre    = "Sci-Fi";
movie.director = "Christopher Nolan";

// Later on, lets add some more property via a dictionary
var dictionary = movie as IDictionary ;
dictionary.Add("Rating", "PG-13");
dictionary.Add("ReleaseDate", "2014-11-07");
dictionary.Add("BlahBlah", "SomeValue");

// Opps! Lets remove the field BlahBlah.. 
((IDictionary)movie).Remove("BlahBlah");

Example Usage

So armed with this knowledge, how can we make use of this? Well, a perfect use-case for this is when sending JSON data from a sever to the client. Using this dynamic object the server could tailor the data returned to the client, based on its requirements.

For example, this helper function "ConvertToDynObj" will convert any object to a dynamic ExpandoObject

public static dynamic ConvertToDynObj(object data, List fieldsToCopy = null )
{
    var dynObj = new ExpandoObject() as IDictionary;

    foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(data.GetType()))
    {
        if (fieldsToCopy == null )
        {
            dynObj.Add(property.Name, property.GetValue(data));
        }
        else if (fieldsToCopy.Contains(property.Name) == true)
        {
            // we only want to include this field in the new dynamic type
            dynObj.Add(property.Name, property.GetValue(data));
        }
    }

    return dynObj;
}
With the helper function defined above, we can mutate existing objects in our class library. Lets say we have a business object defined in our system that looks like this:
class BusinessDuberie
{
    public int fieldOne { get; set; }
    public string fieldTwo { get; set; }
    public double fieldThree { get; set; }

    public BusinessDuberie()
    {
        fieldOne = 1; fieldTwo = "2"; fieldThree = 3.3; 
    }
}
We can now convert the object to a dynamic object wholesale like this:
BusinessDuberie obj = new BusinessDuberie();

var dynObj = ConvertToDynObj(obj);

// Now we can add properties on the fly

(dynObj as IDictionary).Add("Qwerty", "Berty");

We could also trim the object and only copy the properties we are interested in.

List fieldsToCopy
fieldsToCopy.add("fieldOne");
fieldsToCopy.add("fieldThree");

var dynObj = ConvertToDynObj( obj, fieldsToCopy );
Now that's what I call sweet.

Contact Me:  ocean.airdrop@gmail.com

Popular Posts

Recent Posts

Unordered List

Text Widget

Pages