private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue, out object newValue, out string id)
        {
            id = null;
            newValue = null;

            if (reader.TokenType == JsonToken.StartObject)
            {
                JObject current = (JObject)reader.CurrentToken;

                JToken refToken = current[JsonTypeReflector.RefPropertyName];
                if (refToken != null)
                {
                    if (refToken.Type != JTokenType.String && refToken.Type != JTokenType.Null)
                    {
                        throw JsonSerializationException.Create(refToken, refToken.Path, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName), null);
                    }

                    JToken property = refToken.Parent;
                    JToken additionalContent = null;
                    if (property.Next != null)
                    {
                        additionalContent = property.Next;
                    }
                    else if (property.Previous != null)
                    {
                        additionalContent = property.Previous;
                    }

                    string reference = (string)refToken;

                    if (reference != null)
                    {
                        if (additionalContent != null)
                        {
                            throw JsonSerializationException.Create(additionalContent, additionalContent.Path, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName), null);
                        }

                        newValue = Serializer.GetReferenceResolver().ResolveReference(this, reference);

                        if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
                        {
                            TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, reference, newValue.GetType())), null);
                        }

                        reader.Skip();
                        return true;
                    }
                }
                JToken typeToken = current[JsonTypeReflector.TypePropertyName];
                if (typeToken != null)
                {
                    string qualifiedTypeName = (string)typeToken;
                    JsonReader typeTokenReader = typeToken.CreateReader();
                    typeTokenReader.ReadAndAssert();
                    ResolveTypeName(typeTokenReader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName);

                    JToken valueToken = current[JsonTypeReflector.ValuePropertyName];
                    if (valueToken != null)
                    {
                        while (true)
                        {
                            reader.ReadAndAssert();
                            if (reader.TokenType == JsonToken.PropertyName)
                            {
                                if ((string)reader.Value == JsonTypeReflector.ValuePropertyName)
                                {
                                    return false;
                                }
                            }

                            reader.ReadAndAssert();
                            reader.Skip();
                        }
                    }
                }
                JToken idToken = current[JsonTypeReflector.IdPropertyName];
                if (idToken != null)
                {
                    id = (string)idToken;
                }
                JToken valuesToken = current[JsonTypeReflector.ArrayValuesPropertyName];
                if (valuesToken != null)
                {
                    JsonReader listReader = valuesToken.CreateReader();
                    listReader.ReadAndAssert();
                    newValue = CreateList(listReader, objectType, contract, member, existingValue, id);

                    reader.Skip();
                    return true;
                }
            }

            reader.ReadAndAssert();
            return false;
        }