As many oth­ers have shown, the new ExpandoOb­ject intro­duced in C# 4 can be pretty use­ful in some scenarios.

How­ever, on the odd occa­sion when you want to con­vert an ExpandoOb­ject to a sta­tic type you have defined you can be for­given for feel­ing a lit­tle lost as there are no well doc­u­mented ways to do that. At least that’s how I felt, until I found out about the Con­vert­To­Type meth­ods on the JavaScript­Se­ri­al­izer!

JavaScript­Se­ri­al­izer

The JavaScript­Se­ri­al­izer, like the Dat­a­Con­trac­tJ­son­Se­ri­al­izer class, lets you seri­al­ize and dese­ri­al­ize objects to and from JSON string. But unlike the Dat­a­Con­trac­tJ­son­Se­ri­al­izer class, you are not con­fined to work­ing with types that are marked with the Dat­a­Con­tract attribute.

One of the dese­ri­al­iza­tion meth­ods on the JavaScript­Se­ri­al­izer class – Dese­ri­al­izeOb­ject – lets you a JSON string to an object graph, i.e. a Dictionary<string, object> object where the key is the name of the prop­erty and the value is the prop­erty value. And you can use one of the over­loaded Con­vert­To­Type meth­ods to con­vert this dic­tio­nary to a sta­tic type of your choice, pro­vided that the type has a para­me­ter­less con­struc­tor (which unfor­tu­nately, means you won’t be able to con­vert an ExpandoOb­ject to an anony­mous type).

ExpandoOb­ject as IDictionary<string, object>

Why is this impor­tant? It’s because the ExpandoOb­ject imple­ments the IDictionary<string, object> inter­face and there­fore can be used with the Con­vert­To­Type methods!

Here’s what you do:

   1: // first you need to instantiate the serializer

   2: var jsSerializer = new JavaScriptSerializer();

   3:

   4: // get an expando object and convert it to an instance of MyClass

   5: var expando = GetExpandoObject();

   6: var obj = jsSerializer.ConvertToType<MyClass>(expando);

   7:

   8: Console.WriteLine(obj.Id);      // 0db9d9a6-8c7e-4bea-82a8-4d5641c7c0de

   9: Console.WriteLine(obj.Name);    // Yan

  10: Console.WriteLine(obj.Age);     // 29

  11:

  12: ...

  13:

  14: public ExpandoObject GetExpandoObject()

  15: {

  16:     dynamic expando = new ExpandoObject();

  17:     expando.Id = Guid.NewGuid();

  18:     expando.Name = "Yan";

  19:     expando.Age = 29;

  20:

  21:     return expando;

  22: }

  23:

  24: public class MyClass

  25: {

  26:     public Guid Id { get; set; }

  27:

  28:     public string Name { get; set; }

  29:

  30:     public int Age { get; set; }

  31: }

Pretty cool, eh? ;-)

But what if the shape of the expando object doesn’t match your type? E.g. there are prop­er­ties defined on MyClass but not on the expando object, or vice versa, or both? Well, it’s smart enough to work that out itself and only set the prop­er­ties which it is able to set:

   1: // same as before

   2:

   3: Console.WriteLine(obj.Id);          // 0db9d9a6-8c7e-4bea-82a8-4d5641c7c0de

   4: Console.WriteLine(obj.Name);        // null

   5: Console.WriteLine(obj.Age);         // 29

   6: Console.WriteLine(obj.NickName);    // null

   7:

   8: ...

   9:

  10: public ExpandoObject GetExpandoObject()

  11: {

  12:     dynamic expando = new ExpandoObject();

  13:     expando.Id = Guid.NewGuid();

  14:     expando.Name = "Yan";

  15:     expando.Age = 29;

  16:     expando.Wife = "Yinan";    // not defined on MyClass

  17:

  18:     return expando;

  19: }

  20:

  21: public class MyClass

  22: {

  23:     public Guid Id { get; set; }

  24:

  25:     public string Name { get; private set; } // non-public setter

  26:

  27:     public int Age { get; set; }

  28:

  29:     public string NickName { get; set; } // not defined on ExpandoObject

  30: }

Share

Leave a Reply