Monday, 21 August 2017

Some C# dynamic coolness

In the last days I've found some interesting things regarding the use of C# dynamic. I'll put it here.

Implementing Multiple Dispatch. The common use of dynamic is calling a method in a dynamic object. We are getting runtime single dispatch based on the object on which the method is invoked. Either the object itself if it implements IDynamicMetaObjectProvider, or the runtime via reflection, will find the method to invoke. I was not aware that this also applies when the dynamic object is used as parameter. The runtime will check its type and if several methods with the same name exist but with different argument types, it will invoke the correct one based on the runtime type. You can find a cute example here. This is pretty interesting because the runtime will use Reflection to match types with methods, doing on your behalf something that in the almighty JavaScript you would have to do on your own. By the way, this brings to my mind this explanation by Eric Lippert of the differences between using Reflection "manually" and Dynamic

Dynamic and Anonymous Types. At the time of its inception (C# 3) Anonymous Types were pretty limited. The compiler will create a class for your Anonymous Type, but you have no access to its name (so you can not do a cast), meaning that you can only access "freely" to its fields inside the method where they are created (you'll declare it as var and the compiler will use the correct type inside that method). If you return an instance of an Anonymous Object from your method, you'll be returning just an Object (you can not cast them to an inteface nor anything), so in order to access its fields you'll have to use Reflection manually.
Well, we know that dynamic will take care of using Reflection of its own (and pretty effectively thanks to caching), so we can do this:

//It's just the same if we set the return type to "dynamic" or "object" in both cases the compiler will generate a method return "Object"
//static dynamic CreateObject(int flag)
static object CreateObject(int flag)
{
  return new {Name="Francois"};
}
    
static void Main(string[] args)
{
 dynamic ob = CreateObject(0);
 Console.WriteLine(ob.Name);
}

You should notice an important limitation. Fields in Anonymous Types are internal, and when dynamic uses Reflection it plays by the rules, so it won't work if the Anonymous Type was defined in another Assembly.

Json.Net, JValue and implicit conversions. Json.NET has had an excellent dynamic support since quite a few years. This makes accessing the tree of properties in a JObject a real bargain:

var jsonString = @"{
 ""city"" : {
  ""name"": ""Toulouse"",
  ""population"" : 466000
 },
 ""otherData"" : ""aaaa"" 
}";
dynamic obj = JObject.Parse(jsonString); //returns a JObject
string cityName = obj.city.name;
Console.WriteLine("City Name: " + cityName);   

JToken (from which the different JContaine, JObject, JValue objects inherit) supports the dynamic machinery by implementing IDynamicMetaObjectProvider and returning a DynamicProxyMetaObject<JToken> (that extends DynamicMetaObject). The use of dynamic for dynamically accessing properties (or methods) of an object is what we are used to, but when you get to the last element, the "name" in my sample, you have a JValue object, so how does the assignment of a JValue to a string work?
This has quite confused me. It seems like there should be some sort of implicit conversion. Well, the thing is that DynamicMetaObject provides a BindConvert method. I've been having a fast look into the Json.NET source code and honestly, I get a bit lost with all those proxies, metaObjects and binders, but I assume somehow the BindConvert somewhere is who is doing "the magic".

No comments:

Post a Comment