Hugoware

The product of a web developer with a little too much caffeine

Almost Sorta Real Dynamic in .NET

with 8 comments

This post discusses the basics of writing your own dynamic type – If you’re interested in the finished code make sure to download the source.

The new dynamic keyword is a great way to create and modify a dynamic object in your .NET code – For example, check out this bit of code.

dynamic counter = new {
    sent = 0,
    received = 0
};
counter.sent++;

… Oh… wait… That doesn’t actually work…

That’s because even though you have an object declared as dynamic, it is still just the same old object it always was under the hood. Maybe not the dynamic utopia we were expecting. Seems like plain ol’ Reflection with a slightly cleaner syntax.

Bummer…

However, Microsoft was awesome enough to actually allow us to create our own dynamic types by simply inheriting from the DynamicObject class. This post looks at how we can create a semi-dynamic object by handling the binding methods ourselves.

[Source Code: Dynamic.cs]

Our goal is to create an object that we can add, remove and change values on the fly. It ends up being a little easier than we expect. Let’s look at the minimum code we are going to need to get started.

public class SimpleDynamic : DynamicObject {

    //contains the values to use
    private Dictionary<string, object> _Values = new Dictionary<string, object>();

    //handles getting values from our object
    public override void TryGetMember(GetMemberBinder binder, out object result) {
        //...
    }

    //handles assigning values to our object
    public override bool TrySetMember(SetMemberBinder binder, object value) {
        //...
    }

}

Note: If you downloaded the source code above you might be wondering why these examples don’t look the same. The source code is the complete Dynamic class while this post only goes over the basics of using the DynamicObject class.

In order to create our dynamic object we must handle getting and setting values. We can use a simple Dictionary<string,object> to hold our values until we need them.

//handles getting values from our object
public override void TryGetMember(GetMemberBinder binder, out object result) {
    return this._Values.TryGetValue(binder.name, out result);
}

//handles assigning values to our object
public override bool TrySetMember(SetMemberBinder binder, object value) {
    this._Values.Remove(binder.name);
    if (value is object) { this._Values.Add(binder.name, value); }
    return true;
}

Not much code, but now our dynamic object is a little more dynamic than it was before. We can now work with properties a lot easier.

//create the new object
dynamic simple = new SimpleDynamic();

//add and update some values
simple.red = "#f00";
simple.green = "#0f0";
simple.count = 10;
simple.add = new Action<int>(value => simple.count += value);

//and check the values
Console.WriteLine(simple.red); // #f00
Console.WriteLine(simple.green); // #0f0
Console.WriteLine(simple.count); // 10

//invoke methods
simple.add(5);
Console.WriteLine(simple.count); // 15

Of course this class isn’t that helpful since it’s only regular Dictionary without string indexes but it is interesting to see how you can make a ‘dynamic’ object with only a few lines of code.

As for the included source code, it has a few extra features that this class doesn’t have.

  • Use Anonymous Types directly to build out entire objects.
  • Support for the += operator.
  • Enumeration through member names.
  • String indexes (for both single and nested properties).

Here are a few examples the Dynamic.cs class can do.

//create using anonymous types (and nested anonymous types)
dynamic info = new Dynamic(new {
    name = "Hugo",
    age = 30,
    settings = new {
        color = "orange",
        homepage = "website.com"
    }});

//add values using +=
info.create = new { value = false; }
info.nested.value.allowed = 55;

//enumeration of properties
foreach(string prop in info) {
    Console.WriteLine("{0}: {1}", prop, info[prop]);
}

I’d caution against using this a lot in your projects, but it is really interesting to see the kind of control Microsoft has built into the new DynamicObject class.

[Source Code: Dynamic.cs]

Advertisements

Written by hugoware

July 15, 2010 at 12:32 am

8 Responses

Subscribe to comments with RSS.

  1. You could have simply used the ExpandoObject.

    Batzen

    July 15, 2010 at 9:32 am

    • Yes, ExpandoObject is pretty close, but not exactly what I was looking for – For example, here is something Dynamic.cs can do that ExpandoObject cannot.

      --------------------------------
      //Dynamic.cs
      dynamic dyna = new Dynamic();
      dyna.person = new { first = "Joe" };
      dyna.person += new { last = "Smith" };
      dyna.person.middle = "M";
      dyna.person.full = string.Format(
      	"{0} {1} {2}", 
      	dyna.person.first,
      	dyna.person.middle,
      	dyna.person.last);
      
      //Displays: Joe M Smith
      Console.WriteLine(dyna.person.full);
      
      //ExpandoObject
      dynamic obj = new ExpandoObject();
      obj.person = new { first = "Joe" };
      obj.person += new { last = "Smith" };
      obj.person.middle = "M";
      obj.person.full = string.Format(
      	"{0} {1} {2}",
      	obj.person.first,
      	obj.person.middle,
      	obj.person.last);
      
      //Won't make it here - Crashes earlier
      Console.WriteLine(obj.person.full);
      --------------------------------
      

      Dynamic.cs is geared to modifying a full tree of objects dynamically instead of single properties or ready only Anonymous Types.

      As another example…

      --------------------------------
      //Dynamic.cs
      dynamic dyna = new Dynamic();
      dyna.total = new {
      	shipped = 0,
      	received = 0
      };
      dyna.total.shipped += 100;
      
      //Display: 100
      Console.WriteLine(dyna.total.shipped);
      
      //ExpandoObject
      dynamic obj = new ExpandoObject();
      obj.total = new {
      	shipped = 0,
      	received = 0
      };
      obj.total.shipped += 100;
      
      //Crashes before this line
      Console.WriteLine(obj.total.shipped);
      --------------------------------
      

      Anyways, just some code I was playing with.

      Thanks for the comment!

      hugoware

      July 15, 2010 at 11:52 am

  2. Nice. With this, I finally tried the dynamic keyword in c#. I found a little error though which prevented the application from running:
    public Dynamic()
    {
    this._Values = new _DynamicDictionary();
    }

    public Dynamic(object value):this()
    {
    Dynamic._Merge(this, value);
    }
    The “:this()” was missing so I was getting a NullReferenceException since _Values was null.

    With it working, my next concern was getting the data as json. As it stands, using JsonConvert from NewtonSoft.Json simply returns the names of the properties. Really like the ability to use += on the object.

    Richard

    August 1, 2010 at 7:16 am

  3. Hi,

    Your idea is fine, I like it, better than ExpandoObject.

    I have two issues:
    1. It does not compile, I just downloaded and tried, it gives an error that the IEnumerator requires 1 type argument. I’m using framework 4.0, so maybe that is more strict than previous versions, I haven’t tried it in earlier versions.
    2. It would be nice if there will be a way to have something like new { name:”David, age:35 }, so we can initialize an object in a single line just as javascript. I don’t know if it’s possible, I’m not that expert in asp.net.

    That’s it, thanks for the help.

    Zohar

    September 1, 2010 at 1:09 pm

    • Hi Zohar,

      You might check and make sure you have included System.Collections at the top of your class file. I think that is probably why you are getting the error message.

      hugoware

      September 2, 2010 at 12:42 am

      • Yes, that’s was it, It works great now.

        It also has a good advantage over ExpandoObject
        that you can initialize the values in the constructor, which makes my code simpler:

        dynamic item = new Dynamic(new { name = “David”, age = 35 } );

        I really like it!
        Thanks

        Zohar

        September 2, 2010 at 6:21 am

  4. […] Almost Sorta Real Dynamic in .NET […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: