I just stumbled over the neat post about how to turning JSON into a ExpandoObject the other day about how to work with json-data on the server side using the new dynamic features in .NET 4.0.
What I wanted to achieve was to serialize my JavaScript view models into C#. I knew I could write a custom model binder for that but since the view model was quite complicated I figured that it would probably be best if I had full control over the deserialization. At least for now…
public class JsViewModel { public int Id { get; set; } public static JsViewModel CreateModelFromJson(dynamic json) { string type = json.type; string typeName = (typeof(JsViewModel).Namespace) + "." + type; try { var def = (JsViewModel)Activator.CreateInstance(Type.GetType(typeName)); def.Deserialize(json); return def; } catch (Exception e) { //... return None; } } public virtual void Deserialize(dynamic json) { this.Id = json.id; } }
The above code worked fine, I could pass in any type as long as it had a property called type.
But when I started implementing my view models I soon run into trouble.
public class MyJsViewModel: JsViewModelDefinition { public string Name { get; set; } public override void Deserialize(dynamic json) { base.Deserialize(json); Name = json.shortName; } }
Error 66 The call to method ‘Deserialize’ needs to be dynamically dispatched, but cannot be because it is part of a base access expression. Consider casting the dynamic arguments or eliminating the base access.
Ouch, seems like you can’t really do the stuff I was hoping for and since giving up base access is out of the question for me I had to go with the casting option.
I knew that my json would be represented using the ExpandoObject (see the turning JSON into a ExpandoObject blog post above) so I could cast it directly into an that but that would break the ability to write simple test cases like JsViewModel.CreateModelFromJson(new{type=”MyJsViewModel”}) so I choose object instead.
public class JsViewModel { public int Id { get; set; } public static JsViewModel CreateModelFromJson(dynamic json) { String type = json.type; string typeName = (typeof(JsViewModel).Namespace) + "." + type; try { var def = (JsViewModel)Activator.CreateInstance(Type.GetType(typeName)); def.Deserialize(json); return def; } catch (Exception e) { // handle error... } } public virtual void Deserialize(object jsonObject) { dynamic json = jsonObject; this.Id = json.id; } } public class MyJsViewModel: JsViewModel { public string Name { get; set; } public override void Deserialize(object jsonObject) { base.Deserialize(jsonObject); dynamic json = jsonObject; Name = json.shortName; } }
No comments yet.