private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor<object> creator, string id) { ValidationUtils.ArgumentNotNull(creator, "creator"); // only need to keep a track of properies presence if they are required or a value should be defaulted if missing Dictionary<JsonProperty, PropertyPresence> propertiesPresence = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate)) ? contract.Properties.ToDictionary(m => m, m => PropertyPresence.None) : null; Type objectType = contract.UnderlyingType; IDictionary<string, object> extensionData; IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndCreatorValues(contract, containerProperty, reader, objectType, out extensionData); object[] creatorParameterValues = new object[contract.CreatorParameters.Count]; IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>(); foreach (KeyValuePair<JsonProperty, object> propertyValue in propertyValues) { JsonProperty property = propertyValue.Key; JsonProperty matchingCreatorParameter; if (contract.CreatorParameters.Contains(property)) { matchingCreatorParameter = property; } else { // check to see if a parameter with the same name as the underlying property name exists and match to that matchingCreatorParameter = contract.CreatorParameters.ForgivingCaseSensitiveFind(p => p.PropertyName, property.UnderlyingName); } if (matchingCreatorParameter != null) { int i = contract.CreatorParameters.IndexOf(matchingCreatorParameter); creatorParameterValues[i] = propertyValue.Value; } else { remainingPropertyValues.Add(propertyValue); } if (propertiesPresence != null) { // map from creator property to normal property JsonProperty presenceProperty = propertiesPresence.Keys.FirstOrDefault(p => p.PropertyName == property.PropertyName); if (presenceProperty != null) propertiesPresence[presenceProperty] = (propertyValue.Value == null) ? PropertyPresence.Null : PropertyPresence.Value; } } object createdObject = creator(creatorParameterValues); if (id != null) AddReference(reader, id, createdObject); OnDeserializing(reader, contract, createdObject); // go through unused values and set the newly created object's properties foreach (KeyValuePair<JsonProperty, object> remainingPropertyValue in remainingPropertyValues) { JsonProperty property = remainingPropertyValue.Key; object value = remainingPropertyValue.Value; if (ShouldSetPropertyValue(property, value)) { property.ValueProvider.SetValue(createdObject, value); } else if (!property.Writable && value != null) { // handle readonly collection/dictionary properties JsonContract propertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType); if (propertyContract.ContractType == JsonContractType.Array) { JsonArrayContract propertyArrayContract = (JsonArrayContract)propertyContract; object createdObjectCollection = property.ValueProvider.GetValue(createdObject); if (createdObjectCollection != null) { IWrappedCollection createdObjectCollectionWrapper = propertyArrayContract.CreateWrapper(createdObjectCollection); IWrappedCollection newValues = propertyArrayContract.CreateWrapper(value); foreach (object newValue in newValues) { createdObjectCollectionWrapper.Add(newValue); } } } else if (propertyContract.ContractType == JsonContractType.Dictionary) { JsonDictionaryContract dictionaryContract = (JsonDictionaryContract)propertyContract; object createdObjectDictionary = property.ValueProvider.GetValue(createdObject); if (createdObjectDictionary != null) { IDictionary targetDictionary = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(createdObjectDictionary) : (IDictionary)createdObjectDictionary; IDictionary newValues = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(value) : (IDictionary)value; foreach (DictionaryEntry newValue in newValues) { targetDictionary.Add(newValue.Key, newValue.Value); } } } } } if (extensionData != null) { foreach (KeyValuePair<string, object> e in extensionData) { contract.ExtensionDataSetter(createdObject, e.Key, e.Value); } } EndObject(createdObject, reader, contract, reader.Depth, propertiesPresence); OnDeserialized(reader, contract, createdObject); return createdObject; }
private void SetExtensionData(JsonObjectContract contract, JsonProperty member, JsonReader reader, string memberName, object o) { if (contract.ExtensionDataSetter != null) { try { object value = CreateValueInternal(reader, null, null, null, contract, member, null); contract.ExtensionDataSetter(o, memberName, value); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error setting value in extension data for type '{0}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType), ex); } } else { reader.Skip(); } }