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();
			}
		}
		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;

			if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) {
				string parameters = string.Join(", ", contract.CreatorParameters.Select(p => p.PropertyName).ToArray());
				TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using creator with parameters: {1}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, parameters)), null);
			}

			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;
		}