private void SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
    {
      contract.InvokeOnSerializing(values.UnderlyingCollection, Serializer.Context);

      _serializeStack.Add(values.UnderlyingCollection);

      bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty);

      writer.WriteStartArray();

      int initialDepth = writer.Top;

      int index = 0;
      // note that an error in the IEnumerable won't be caught
      foreach (object value in values)
      {
        try
        {
          JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);

          if (ShouldWriteReference(value, null, valueContract, contract, member))
          {
            WriteReference(writer, value);
          }
          else
          {
            if (CheckForCircularReference(writer, value, null, valueContract, contract, member))
            {
              SerializeValue(writer, value, valueContract, null, contract, member);
            }
          }
        }
        catch (Exception ex)
        {
          if (IsErrorHandled(values.UnderlyingCollection, contract, index, writer.ContainerPath, ex))
            HandleError(writer, initialDepth);
          else
            throw;
        }
        finally
        {
          index++;
        }
      }

      writer.WriteEndArray();

      if (hasWrittenMetadataObject)
        writer.WriteEndObject();

      _serializeStack.RemoveAt(_serializeStack.Count - 1);

      contract.InvokeOnSerialized(values.UnderlyingCollection, Serializer.Context);
    }
    private bool WriteStartArray(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
    {
      bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer.PreserveReferencesHandling, PreserveReferencesHandling.Arrays);
      bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty);
      bool writeMetadataObject = isReference || includeTypeDetails;

      if (writeMetadataObject)
      {
        writer.WriteStartObject();

        if (isReference)
        {
          writer.WritePropertyName(JsonTypeReflector.IdPropertyName);
          writer.WriteValue(Serializer.ReferenceResolver.GetReference(this, values.UnderlyingCollection));
        }
        if (includeTypeDetails)
        {
          WriteTypeProperty(writer, values.UnderlyingCollection.GetType());
        }
        writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName);
      }

      if (contract.ItemContract == null)
        contract.ItemContract = Serializer.ContractResolver.ResolveContract(contract.CollectionItemType ?? typeof (object));

      return writeMetadataObject;
    }
    private object PopulateList(IWrappedCollection wrappedList, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
    {
      object list = wrappedList.UnderlyingCollection;

      if (id != null)
        Serializer.ReferenceResolver.AddReference(this, id, list);

      // can't populate an existing array
      if (wrappedList.IsFixedSize)
      {
        reader.Skip();
        return list;
      }

      contract.InvokeOnDeserializing(list, Serializer.Context);

      int initialDepth = reader.Depth;

      JsonContract collectionItemContract = GetContractSafe(contract.CollectionItemType);
      JsonConverter collectionItemConverter = GetConverter(collectionItemContract, null, contract, containerProperty);

      int? previousErrorIndex = null;

      while (true)
      {
        try
        {
          if (ReadForType(reader, collectionItemContract, collectionItemConverter != null))
          {
            switch (reader.TokenType)
            {
              case JsonToken.EndArray:
                contract.InvokeOnDeserialized(list, Serializer.Context);

                return list;
              case JsonToken.Comment:
                break;
              default:
                object value;

                if (collectionItemConverter != null && collectionItemConverter.CanRead)
                  value = collectionItemConverter.ReadJson(reader, contract.CollectionItemType, null, GetInternalSerializer());
                else
                  value = CreateValueInternal(reader, contract.CollectionItemType, collectionItemContract, null, contract, containerProperty, null);

                wrappedList.Add(value);
                break;
            }
          }
          else
          {
            break;
          }
        }
        catch (Exception ex)
        {
          JsonPosition errorPosition = reader.GetPosition(initialDepth);

          if (IsErrorHandled(list, contract, errorPosition.Position, reader.Path, ex))
          {
            HandleError(reader, true, initialDepth);

            if (previousErrorIndex != null && previousErrorIndex == errorPosition.Position)
            {
              // reader index has not moved since previous error handling
              // break out of reading array to prevent infinite loop
              throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex);
            }
            else
            {
              previousErrorIndex = errorPosition.Position;
            }
          }
          else
          {
            throw;
          }
        }
      }

      throw JsonSerializationException.Create(reader, "Unexpected end when deserializing array.");
    }