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!
Later, if you want to add a new member variable or a function at run-time.. Just add it!
var movie = new Object();
movie.name = "Interstellar";
movie.genre = "Sci-Fi";
movie.director = "Christopher Nolan";
movie.Rating = 8;And of course you could do the same thing using the object literal notation:
var movie2 = {and later:
name: "Aliens",
genre:"Action",
director:"James Cameron"
};
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.
In essence, the dynamic ExpandoObject lets you add (expand) and remove (contract) member properties & functions of an object.
dynamic movie = new ExpandoObject ();
movie.name = "Interstellar";
movie.genre = "Sci-Fi";
movie.director = "Christopher Nolan";
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, ListWith 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: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;
}
class BusinessDuberieWe can now convert the object to a dynamic object wholesale like this:
{
public int fieldOne { get; set; }
public string fieldTwo { get; set; }
public double fieldThree { get; set; }
public BusinessDuberie()
{
fieldOne = 1; fieldTwo = "2"; fieldThree = 3.3;
}
}
BusinessDuberie obj = new BusinessDuberie();We could also trim the object and only copy the properties we are interested in.
var dynObj = ConvertToDynObj(obj);
// Now we can add properties on the fly
(dynObj as IDictionary).Add("Qwerty", "Berty");
ListNow that's what I call sweet.fieldsToCopy
fieldsToCopy.add("fieldOne");
fieldsToCopy.add("fieldThree");
var dynObj = ConvertToDynObj( obj, fieldsToCopy );
Comments
Post a Comment