I have a simple control method DoSomething
which receives a json string, converts it to a dynamic object and tries to get the data:
[HttpPost]
public string DoSomething(string jsonStr) // {"0":null,"1":"loadData"}
{
// In this case obj.GetType() = System.Web.Helpers.DynamicJsonObject
object obj = Json.Decode(jsonStr);
// Correct, a == "loadData"
var a = (obj as dynamic)["1"];
// Incorrect, compilation exception:
// "Cannot apply indexing with [] to an expression
// of type 'System.Web.Helpers.DynamicJsonObject'"
var b = (obj as DynamicJsonObject)["1"]
return "OK";
}
My question is why it is possible to access an indexer when I use an object as a dynamic object at the time when the original type doesn't have an indexer?
In the first case, you're using all the infrastructure of dynamic
- which doesn't just use reflection to find "real" members, but also uses IDynamicMetaObjectProvider
to provide support for members which are only known at execution time. This works because when you're using dynamic
, the process of binding (working out what a member name means) is performed at execution time instead of at compile time.
In this case, it's the indexer which is being used at execution time - DynamicJsonObject
doesn't declare an indexer, but overrides the TryGetIndex
method of DynamicObject
. The meta-object provider implementation of DynamicObject
will route indexer "get" calls via TryGetIndex
.
A simpler example of this is ExpandoObject
:
ExpandoObject foo = new ExpandoObject();
// This is invalid; the compiler can't find a Property member
foo.Property = "broken";
dynamic bar = foo;
// This is fine; binding is performed at execution time.
bar.Property = "working";
See more on this question at Stackoverflow