/// <summary>
        /// Serializes a value.
        /// </summary>
        /// <param name="context">The serialization context.</param>
        /// <param name="args">The serialization args.</param>
        /// <param name="value">The object.</param>
        public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TValue value)
        {
            var bsonWriter = context.Writer;

            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                var actualType = value.GetType();
                if (actualType == args.NominalType || args.SerializeAsNominalType)
                {
                    bsonWriter.WriteStartArray();
                    foreach (var item in EnumerateItemsInSerializationOrder(value))
                    {
                        _itemSerializer.Serialize(context, item);
                    }
                    bsonWriter.WriteEndArray();
                }
                else
                {
                    var serializer = new DiscriminatedWrapperSerializer <TValue>(_discriminatorConvention, this);
                    serializer.Serialize(context, value);
                }
            }
        }
        // public methods
        /// <summary>
        /// Deserializes a value.
        /// </summary>
        /// <param name="context">The deserialization context.</param>
        /// <param name="args">The deserialization args.</param>
        /// <returns>A deserialized value.</returns>
        public override TValue Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            var bsonReader = context.Reader;

            var bsonType = bsonReader.GetCurrentBsonType();

            switch (bsonType)
            {
            case BsonType.Null:
                bsonReader.ReadNull();
                return(null);

            case BsonType.Array:
                bsonReader.ReadStartArray();
                var accumulator = CreateAccumulator();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var item = _itemSerializer.Deserialize(context);
                    AddItem(accumulator, item);
                }
                bsonReader.ReadEndArray();
                return(FinalizeResult(accumulator));

            case BsonType.Document:
                var serializer = new DiscriminatedWrapperSerializer <TValue>(_discriminatorConvention, this);
                if (serializer.IsPositionedAtDiscriminatedWrapper(context))
                {
                    return((TValue)serializer.Deserialize(context));
                }
                else
                {
                    goto default;
                }

            default:
                throw CreateCannotDeserializeFromBsonTypeException(bsonType);
            }
        }