Biscuits
Biscuits

Reputation: 1807

Why am I getting a RuntimeBinderException using Json.NET?

The following C# causes a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException on line 2.

dynamic element = JsonConvert.DeserializeObject<dynamic>("{ Key: \"key1\" }");
bool match = "key1".Equals(element.Key, StringComparison.InvariantCulture);

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Member 'object.Equals(object, object)' cannot be accessed with an instance reference; qualify it with a type name instead

The project references Json.NET 8.0.3

<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net452" />

I'm able to circumvent the exception by explicitly converting element.Key to a System.String.

bool match = "key1".Equals((string)element.Key, StringComparison.InvariantCulture);

When checking element.Key.GetType(), a Newtonsoft.Json.Linq.JValue is returned.

Why is it that DLR does not seem to know which method to invoke and ends up calling the static method object.Equals(object, object)?

Edit:

As Amit Kumar Ghosh pointed out, this probably has nothing to do with dynamic types, since converting to System.Object also causes the exception.

bool match = "key1".Equals((object)element.Key, StringComparison.InvariantCulture);

Upvotes: 4

Views: 1920

Answers (2)

CodeCaster
CodeCaster

Reputation: 151738

Why is it that DLR does not seem to know which method to invoke and ends up calling the static method object.Equals(object, object)?

Because element.Key isn't a string, but is of type JToken, which when inspecting it in the debugger looks an awful lot like a string.

This causes the overload resolution at runtime to pick the best match: the static object.Equals(objA, objB), as it can't call string.Equals(value, comparisonType), because the first parameter isn't a string.

You can reproduce this with any dynamic object's non-string property:

dynamic foo = new { Foo = false };
bool equals = "Bar".Equals(foo.Foo, StringComparison.InvariantCulture);

Throws the same exception.

Upvotes: 1

Gabriel Gon&#231;alves
Gabriel Gon&#231;alves

Reputation: 121

Have you tried to use ExpandoObject?

dynamic element = new ExpandoObject();
        element = JsonConvert.DeserializeObject<ExpandoObject>("{ Key: \"key1\" }");            
        bool match = "key1".Equals(element.Key, StringComparison.InvariantCulture); 

Example: https://blogs.msdn.microsoft.com/csharpfaq/2009/09/30/dynamic-in-c-4-0-introducing-the-expandoobject/

Upvotes: 0

Related Questions