public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // Logic adapted from JsonSerializerInternalReader.CreateDynamic() // https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs#L1751 // By James Newton-King https://github.com/JamesNK var contract = (JsonDynamicContract)serializer.ContractResolver.ResolveContract(objectType); if (reader.TokenType == JsonToken.Null) { return(null); } var jObj = JObject.Load(reader); var used = new HashSet <string>(); var obj = CreateObject(jObj, objectType, serializer, used); foreach (var jProperty in jObj.Properties()) { var memberName = jProperty.Name; if (used.Contains(memberName)) { continue; } // first attempt to find a settable property, otherwise fall back to a dynamic set without type JsonProperty property = contract.Properties.GetClosestMatchProperty(memberName); if (property != null && property.Writable && !property.Ignored) { var propertyValue = jProperty.Value.ToObject(property.PropertyType, serializer); property.ValueProvider.SetValue(obj, propertyValue); } else { object propertyValue; if (jProperty.Value.Type == JTokenType.Null) { propertyValue = null; } else if (jProperty.Value is JValue) { // Primitive propertyValue = ((JValue)jProperty.Value).Value; } else { propertyValue = jProperty.Value.ToObject <IDynamicMetaObjectProvider>(serializer); } // Unfortunately the following is not public! // contract.TrySetMember(obj, memberName, propertyValue); // So we have to duplicate the logic of what Json.NET has already done. CallSiteCache.SetValue(memberName, obj, propertyValue); } } return(obj); }
public override object this[object target, string name] { get { return(CallSiteCache.GetValue(name, target)); } set { CallSiteCache.SetValue(name, target, value); } }