ekonbenefits / impromptu-interface

Static interface to dynamic implementation (duck casting). Uses the DLR combined with Reflect.Emit.
Apache License 2.0
655 stars 67 forks source link

Add overload (or optional parameter) to ActLike to support case insensitivity #11

Closed davidpeden3 closed 9 years ago

davidpeden3 commented 9 years ago

It is common for JSON to be camel-cased and .NET interfaces to be Pascal-cased. Adding case-insensitive binding similar to JSON.NET's behavior would be great. The use case comes up when deserializing JSON to dynamic.

The following two lines of code:

var dynamicValue = JsonConvert.DeserializeObject<dynamic>(value); var duckType = Impromptu.ActLike<TInterface>(dynamicValue);

work as expected when the JSON properties are Pascal-cased but fail when they are camel-cased. Since JSON.NET is told to deserialize into dynamic, it does not bind like it would if you were deserializing to a specific class. Enabling case-insensitivity in the call to ActLike would solve the problem.

jbtule commented 9 years ago

So impromptu uses the same api's as the C# dynamic keyword, which binding is case sensitive, however the dynamic objects themselves don't have to be.

Here is the line for the dynamic object in json.net: https://github.com/JamesNK/Newtonsoft.Json/blob/73a266217bfbcbb90b506d4e56ef2741fe76484f/Src/Newtonsoft.Json/Linq/JObject.cs#L801

What it could possibly do instead is result = instance.GetValue(binder.Name, StringComparison.InvariantCultureIgnoreCase);

There maybe a more better or consistent way to do this with json.net api's, this is just any example.

davidpeden3 commented 9 years ago

I'm cool with "wontfix" but to be clear on what I was asking for, Json.NET can't know (and shouldn't really) to create a dynamic object with Pascal-cased properties when the incoming JSON is camel-cased. With camel-cased properties on the dynamic object, ActLike fails to bind them to the interface (which has Pascal-cased properties) as mentioned. It's not an issue with Json.NET at all. Nonetheless, thanks for the comment.

jbtule commented 9 years ago

ActLike uses the DLR and late binds to JObjectDynamicProxy.TryGetMember whether that method returns true or false determines whether the binding will be successful and what result is set to determines the return value.

When you call JsonConvert.DeserializeObject(value), it doesn't generate a type, it just adds data to a JObject that can be bound with the dynamic keyword, when bound by the dynamic keyword in this case it's the property name is converted to a string and TryGetMember is called with the name passed as an argument, inside that method is the only place your issue can be solved. It works with ImpromptuInterface exactly the same way it works with the dynamic keyword.

davidpeden3 commented 9 years ago

Gotcha. Thanks for the detailed explanation.