/// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                var actualType = value.GetType();
                if (actualType != typeof(object))
                {
                    var message = string.Format("ObjectSerializer can only be used with type System.Object, not type {0}.", actualType.FullName);
                    throw new InvalidOperationException(message);
                }

                bsonWriter.WriteStartDocument();
                bsonWriter.WriteEndDocument();
            }
        }
        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            // note: the DateTime portion cannot be serialized as a BsonType.DateTime because it is NOT in UTC
            var dateTimeOffset = (DateTimeOffset)value;
            var representationSerializationOptions = EnsureSerializationOptions<RepresentationSerializationOptions>(options);

            switch (representationSerializationOptions.Representation)
            {
                case BsonType.Array:
                    bsonWriter.WriteStartArray();
                    bsonWriter.WriteInt64(dateTimeOffset.Ticks);
                    bsonWriter.WriteInt32((int)dateTimeOffset.Offset.TotalMinutes);
                    bsonWriter.WriteEndArray();
                    break;
                case BsonType.Document:
                    bsonWriter.WriteStartDocument();
                    bsonWriter.WriteDateTime("DateTime", BsonUtils.ToMillisecondsSinceEpoch(dateTimeOffset.UtcDateTime));
                    bsonWriter.WriteInt64("Ticks", dateTimeOffset.Ticks);
                    bsonWriter.WriteInt32("Offset", (int)dateTimeOffset.Offset.TotalMinutes);
                    bsonWriter.WriteEndDocument();
                    break;
                case BsonType.String:
                    bsonWriter.WriteString(XmlConvert.ToString(dateTimeOffset));
                    break;
                default:
                    var message = string.Format("'{0}' is not a valid DateTimeOffset representation.", representationSerializationOptions.Representation);
                    throw new BsonSerializationException(message);
            }
        }
        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                if (nominalType == typeof(object))
                {
                    var actualType = value.GetType();
                    bsonWriter.WriteStartDocument();
                    bsonWriter.WriteString("_t", TypeNameDiscriminator.GetDiscriminator(actualType));
                    bsonWriter.WriteName("_v");
                    Serialize(bsonWriter, actualType, value, options); // recursive call replacing nominalType with actualType
                    bsonWriter.WriteEndDocument();
                    return;
                }

                var dictionary = (IDictionary)value;
                var dictionarySerializationOptions = EnsureSerializationOptions(options);
                var dictionaryRepresentation = dictionarySerializationOptions.Representation;
                var keyValuePairSerializationOptions = dictionarySerializationOptions.KeyValuePairSerializationOptions;

                if (dictionaryRepresentation == DictionaryRepresentation.Dynamic)
                {
                    dictionaryRepresentation = DictionaryRepresentation.Document;
                    foreach (object key in dictionary.Keys)
                    {
                        var name = key as string; // check for null and type string at the same time
                        if (name == null || name[0] == '$' || name.IndexOf('.') != -1)
                        {
                            dictionaryRepresentation = DictionaryRepresentation.ArrayOfArrays;
                            break;
                        }
                    }
                }

                switch (dictionaryRepresentation)
                {
                    case DictionaryRepresentation.Document:
                        bsonWriter.WriteStartDocument();
                        foreach (DictionaryEntry dictionaryEntry in dictionary)
                        {
                            bsonWriter.WriteName((string)dictionaryEntry.Key);
                            BsonSerializer.Serialize(bsonWriter, typeof(object), dictionaryEntry.Value, keyValuePairSerializationOptions.ValueSerializationOptions);
                        }
                        bsonWriter.WriteEndDocument();
                        break;

                    case DictionaryRepresentation.ArrayOfArrays:
                    case DictionaryRepresentation.ArrayOfDocuments:
                        // override KeyValuePair representation if necessary
                        var keyValuePairRepresentation = (dictionaryRepresentation == DictionaryRepresentation.ArrayOfArrays) ? BsonType.Array : BsonType.Document;
                        if (keyValuePairSerializationOptions.Representation != keyValuePairRepresentation)
                        {
                            keyValuePairSerializationOptions = new KeyValuePairSerializationOptions(
                                keyValuePairRepresentation,
                                keyValuePairSerializationOptions.KeySerializationOptions,
                                keyValuePairSerializationOptions.ValueSerializationOptions);
                        }

                        bsonWriter.WriteStartArray();
                        foreach (DictionaryEntry dictionaryEntry in dictionary)
                        {
                            var keyValuePair = new KeyValuePair<object, object>(dictionaryEntry.Key, dictionaryEntry.Value);
                            _keyValuePairSerializer.Serialize(
                                bsonWriter,
                                typeof(KeyValuePair<object, object>),
                                keyValuePair,
                                keyValuePairSerializationOptions);
                        }
                        bsonWriter.WriteEndArray();
                        break;
                    default:
                        var message = string.Format("'{0}' is not a valid IDictionary representation.", dictionaryRepresentation);
                        throw new BsonSerializationException(message);
                }
            }
        }
        /// <summary>
        /// Serializes a Bitmap to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The Bitmap.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (nominalType != typeof(Image) && nominalType != typeof(Bitmap))
            {
                var message = string.Format("Nominal type must be Image or Bitmap, not {0}.", nominalType.FullName);
                throw new ArgumentException(message, "nominalType");
            }

            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                var actualType = value.GetType();
                if (actualType != typeof(Bitmap))
                {
                    var message = string.Format("Actual type must be Bitmap, not {0}.", actualType.FullName);
                    throw new ArgumentException(message, "actualType");
                }

                var bitmap = (Bitmap)value;
                var stream = new MemoryStream();
                bitmap.Save(stream, ImageFormat.Bmp);
                var bytes = stream.ToArray();

                if (nominalType == typeof(Image))
                {
                    bsonWriter.WriteStartDocument();
                    bsonWriter.WriteString("_t", "Bitmap");
                    bsonWriter.WriteBinaryData("bitmap", bytes, BsonBinarySubType.Binary);
                    bsonWriter.WriteEndDocument();
                }
                else
                {
                    bsonWriter.WriteBinaryData(bytes, BsonBinarySubType.Binary);
                }
            }
        }
        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                // Nullable types are weird because they get boxed as their underlying value type
                // we can best handle that by switching the nominalType to the underlying value type
                // (so VerifyNominalType doesn't fail and we don't get an unnecessary discriminator)
                if (nominalType.IsGenericType && nominalType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    nominalType = nominalType.GetGenericArguments()[0];
                }

                VerifyNominalType(nominalType);
                var actualType = (value == null) ? nominalType : value.GetType();
                if (actualType != _classMap.ClassType)
                {
                    var message = string.Format("BsonClassMapSerializer.Serialize for type {0} was called with actualType {1}.",
                        BsonUtils.GetFriendlyTypeName(_classMap.ClassType), BsonUtils.GetFriendlyTypeName(actualType));
                    throw new BsonSerializationException(message);
                }

                var documentSerializationOptions = (options ?? DocumentSerializationOptions.Defaults) as DocumentSerializationOptions;
                if (documentSerializationOptions == null)
                {
                    var message = string.Format(
                        "Serializer BsonClassMapSerializer expected serialization options of type {0}, not {1}.",
                        BsonUtils.GetFriendlyTypeName(typeof(DocumentSerializationOptions)),
                        BsonUtils.GetFriendlyTypeName(options.GetType()));
                    throw new BsonSerializationException(message);
                }

                bsonWriter.WriteStartDocument();
                BsonMemberMap idMemberMap = null;
                if (documentSerializationOptions.SerializeIdFirst)
                {
                    idMemberMap = _classMap.IdMemberMap;
                    if (idMemberMap != null)
                    {
                        SerializeMember(bsonWriter, value, idMemberMap);
                    }
                }

                if (actualType != nominalType || _classMap.DiscriminatorIsRequired || _classMap.HasRootClass)
                {
                    // never write out a discriminator for an anonymous class
                    if (!_classMap.IsAnonymous)
                    {
                        var discriminatorConvention = _classMap.GetDiscriminatorConvention();
                        var discriminator = discriminatorConvention.GetDiscriminator(nominalType, actualType);
                        if (discriminator != null)
                        {
                            bsonWriter.WriteName(discriminatorConvention.ElementName);
                            BsonValueSerializer.Instance.Serialize(bsonWriter, typeof(BsonValue), discriminator, null);
                        }
                    }
                }

                var allMemberMaps = _classMap.AllMemberMaps;
                var extraElementsMemberMapIndex = _classMap.ExtraElementsMemberMapIndex;

                for (var memberMapIndex = 0; memberMapIndex < allMemberMaps.Count; ++memberMapIndex)
                {
                    var memberMap = allMemberMaps[memberMapIndex];
                    // note: if serializeIdFirst is false then idMemberMap will be null (so no property will be skipped)
                    if (memberMap != idMemberMap)
                    {
                        if (memberMapIndex != extraElementsMemberMapIndex)
                        {
                            SerializeMember(bsonWriter, value, memberMap);
                        }
                        else
                        {
                            SerializeExtraElements(bsonWriter, value, memberMap);
                        }
                    }
                }
                bsonWriter.WriteEndDocument();
            }
        }
 /// <summary>
 /// Serializes an object to a BsonWriter.
 /// </summary>
 /// <param name="bsonWriter">The BsonWriter.</param>
 /// <param name="nominalType">The nominal type.</param>
 /// <param name="value">The object.</param>
 /// <param name="options">The serialization options.</param>
 public override void Serialize(
     BsonWriter bsonWriter,
     Type nominalType,
     object value,
     IBsonSerializationOptions options)
 {
     if (value == null)
     {
         bsonWriter.WriteStartDocument();
         bsonWriter.WriteBoolean("_csharpnull", true);
         bsonWriter.WriteEndDocument();
     }
     else
     {
         BsonValueSerializer.Instance.Serialize(bsonWriter, nominalType, value, options);
     }
 }
 /// <summary>
 /// Serializes an object to a BsonWriter.
 /// </summary>
 /// <param name="bsonWriter">The BsonWriter.</param>
 /// <param name="nominalType">The nominal type.</param>
 /// <param name="value">The object.</param>
 /// <param name="options">The serialization options.</param>
 public override void Serialize(
     BsonWriter bsonWriter,
     Type nominalType,
     object value,
     IBsonSerializationOptions options)
 {
     if (value == null)
     {
         bsonWriter.WriteNull();
     }
     else
     {
         var cultureInfo = (CultureInfo)value;
         if (cultureInfo.UseUserOverride)
         {
             // the default for UseUserOverride is true so we don't need to serialize it
             bsonWriter.WriteString(cultureInfo.Name);
         }
         else
         {
             bsonWriter.WriteStartDocument();
             bsonWriter.WriteString("Name", cultureInfo.Name);
             bsonWriter.WriteBoolean("UseUserOverride", cultureInfo.UseUserOverride);
             bsonWriter.WriteEndDocument();
         }
     }
 }
 /// <summary>
 /// Serializes an object of type System.Drawing.Size  to a BsonWriter.
 /// </summary>
 /// <param name="bsonWriter">The BsonWriter.</param>
 /// <param name="nominalType">The nominal type.</param>
 /// <param name="value">The object.</param>
 /// <param name="options">The serialization options.</param>
 public override void Serialize(
     BsonWriter bsonWriter,
     Type nominalType,
     object value,
     IBsonSerializationOptions options)
 {
     var size = (System.Drawing.Size)value;
     bsonWriter.WriteStartDocument();
     bsonWriter.WriteInt32("Width", size.Width);
     bsonWriter.WriteInt32("Height", size.Height);
     bsonWriter.WriteEndDocument();
 }
#pragma warning restore 618

        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                var bitArray = (BitArray)value;
                var representationSerializationOptions = EnsureSerializationOptions<RepresentationSerializationOptions>(options);

                switch (representationSerializationOptions.Representation)
                {
                    case BsonType.Binary:
                        if ((bitArray.Length % 8) == 0)
                        {
                            bsonWriter.WriteBinaryData(GetBytes(bitArray), BsonBinarySubType.Binary);
                        }
                        else
                        {
                            bsonWriter.WriteStartDocument();
                            bsonWriter.WriteInt32("Length", bitArray.Length);
                            bsonWriter.WriteBinaryData("Bytes", GetBytes(bitArray), BsonBinarySubType.Binary);
                            bsonWriter.WriteEndDocument();
                        }
                        break;
                    case BsonType.String:
                        var sb = new StringBuilder(bitArray.Length);
                        for (int i = 0; i < bitArray.Length; i++)
                        {
                            sb.Append(bitArray[i] ? '1' : '0');
                        }
                        bsonWriter.WriteString(sb.ToString());
                        break;
                    default:
                        var message = string.Format("'{0}' is not a valid BitArray representation.", representationSerializationOptions.Representation);
                        throw new BsonSerializationException(message);
                }
            }
        }
        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                var version = (Version)value;
                var representationSerializationOptions = EnsureSerializationOptions<RepresentationSerializationOptions>(options);

                switch (representationSerializationOptions.Representation)
                {
                    case BsonType.Document:
                        bsonWriter.WriteStartDocument();
                        bsonWriter.WriteInt32("Major", version.Major);
                        bsonWriter.WriteInt32("Minor", version.Minor);
                        if (version.Build != -1)
                        {
                            bsonWriter.WriteInt32("Build", version.Build);
                            if (version.Revision != -1)
                            {
                                bsonWriter.WriteInt32("Revision", version.Revision);
                            }
                        }
                        bsonWriter.WriteEndDocument();
                        break;
                    case BsonType.String:
                        bsonWriter.WriteString(version.ToString());
                        break;
                    default:
                        var message = string.Format("'{0}' is not a valid Version representation.", representationSerializationOptions.Representation);
                        throw new BsonSerializationException(message);
                }
            }
        }
        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            // could get here with a BsonDocumentWrapper from BsonValueSerializer switch statement
            var wrapper = value as BsonDocumentWrapper;
            if (wrapper != null)
            {
                BsonDocumentWrapperSerializer.Instance.Serialize(bsonWriter, nominalType, value, null);
                return;
            }

            var rawBsonDocument = value as RawBsonDocument;
            if (rawBsonDocument != null)
            {
                RawBsonDocumentSerializer.Instance.Serialize(bsonWriter, nominalType, value, options);
                return;
            }

            var bsonDocument = (BsonDocument)value;
            var documentSerializationOptions = (options ?? DocumentSerializationOptions.Defaults) as DocumentSerializationOptions;
            if (documentSerializationOptions == null)
            {
                var message = string.Format(
                    "Serialize method of BsonDocument expected serialization options of type {0}, not {1}.",
                    BsonUtils.GetFriendlyTypeName(typeof(DocumentSerializationOptions)),
                    BsonUtils.GetFriendlyTypeName(options.GetType()));
                throw new BsonSerializationException(message);
            }

            bsonWriter.WriteStartDocument();
            BsonElement idElement = null;
            if (documentSerializationOptions.SerializeIdFirst && bsonDocument.TryGetElement("_id", out idElement))
            {
                bsonWriter.WriteName(idElement.Name);
                BsonValueSerializer.Instance.Serialize(bsonWriter, typeof(BsonValue), idElement.Value, null);
            }

            foreach (var element in bsonDocument)
            {
                // if serializeIdFirst is false then idElement will be null and no elements will be skipped
                if (!object.ReferenceEquals(element, idElement))
                {
                    bsonWriter.WriteName(element.Name);
                    BsonValueSerializer.Instance.Serialize(bsonWriter, typeof(BsonValue), element.Value, null);
                }
            }

            bsonWriter.WriteEndDocument();
        }
        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                var actualType = value.GetType();
                var discriminator = GetDiscriminator(nominalType, actualType);
                if (discriminator != null)
                {
                    bsonWriter.WriteStartDocument();
                    bsonWriter.WriteString("_t", discriminator);
                    bsonWriter.WriteName("_v");
                    Serialize(bsonWriter, actualType, value, options);
                    bsonWriter.WriteEndDocument();
                    return;
                }

                var arraySerializationOptions = EnsureSerializationOptions<ArraySerializationOptions>(options);
                var itemSerializationOptions = arraySerializationOptions.ItemSerializationOptions;
                Type lastItemType = null;
                IBsonSerializer lastItemSerializer = null;

                bsonWriter.WriteStartArray();
                foreach (var item in EnumerateItemsInSerializationOrder(value))
                {
                    var itemType = (item == null) ? typeof(object) : item.GetType();
                    IBsonSerializer itemSerializer;
                    if (itemType == lastItemType)
                    {
                        itemSerializer = lastItemSerializer;
                    }
                    else
                    {
                        itemSerializer = BsonSerializer.LookupSerializer(itemType);
                        lastItemType = itemType;
                        lastItemSerializer = itemSerializer;
                    }
                    itemSerializer.Serialize(bsonWriter, typeof(object), item, itemSerializationOptions);
                }
                bsonWriter.WriteEndArray();
            }
        }
        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            var dateTime = (DateTime)value;
            var dateTimeSerializationOptions = EnsureSerializationOptions<DateTimeSerializationOptions>(options);

            DateTime utcDateTime;
            if (dateTimeSerializationOptions.DateOnly)
            {
                if (dateTime.TimeOfDay != TimeSpan.Zero)
                {
                    throw new BsonSerializationException("TimeOfDay component is not zero.");
                }
                utcDateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); // not ToLocalTime
            }
            else
            {
                utcDateTime = BsonUtils.ToUniversalTime(dateTime);
            }
            var millisecondsSinceEpoch = BsonUtils.ToMillisecondsSinceEpoch(utcDateTime);

            switch (dateTimeSerializationOptions.Representation)
            {
                case BsonType.DateTime:
                    bsonWriter.WriteDateTime(millisecondsSinceEpoch);
                    break;
                case BsonType.Document:
                    bsonWriter.WriteStartDocument();
                    bsonWriter.WriteDateTime("DateTime", millisecondsSinceEpoch);
                    bsonWriter.WriteInt64("Ticks", utcDateTime.Ticks);
                    bsonWriter.WriteEndDocument();
                    break;
                case BsonType.Int64:
                    bsonWriter.WriteInt64(utcDateTime.Ticks);
                    break;
                case BsonType.String:
                    if (dateTimeSerializationOptions.DateOnly)
                    {
                        bsonWriter.WriteString(dateTime.ToString("yyyy-MM-dd"));
                    }
                    else
                    {
                        // we're not using XmlConvert.ToString because of bugs in Mono
                        if (dateTime == DateTime.MinValue || dateTime == DateTime.MaxValue)
                        {
                            // serialize MinValue and MaxValue as Unspecified so we do NOT get the time zone offset
                            dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified);
                        }
                        else if (dateTime.Kind == DateTimeKind.Unspecified)
                        {
                            // serialize Unspecified as Local se we get the time zone offset
                            dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
                        }
                        bsonWriter.WriteString(dateTime.ToString("yyyy-MM-ddTHH:mm:ss.FFFFFFFK"));
                    }
                    break;
                default:
                    var message = string.Format("'{0}' is not a valid DateTime representation.", dateTimeSerializationOptions.Representation);
                    throw new BsonSerializationException(message);
            }
        }
        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                if (nominalType == typeof(object))
                {
                    var actualType = value.GetType();
                    bsonWriter.WriteStartDocument();
                    bsonWriter.WriteString("_t", TypeNameDiscriminator.GetDiscriminator(actualType));
                    bsonWriter.WriteName("_v");
                    Serialize(bsonWriter, actualType, value, options);
                    bsonWriter.WriteEndDocument();
                    return;
                }

                var items = ((Stack)value).ToArray(); // convert to array to allow efficient access in reverse order
                var arraySerializationOptions = EnsureSerializationOptions<ArraySerializationOptions>(options);
                var itemSerializationOptions = arraySerializationOptions.ItemSerializationOptions;

                // serialize first pushed item first (reverse of enumeration order)
                bsonWriter.WriteStartArray();
                for (var i = items.Length - 1; i >= 0; i--)
                {
                    BsonSerializer.Serialize(bsonWriter, typeof(object), items[i], itemSerializationOptions);
                }
                bsonWriter.WriteEndArray();
            }
        }
        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                if (nominalType == typeof(object))
                {
                    var actualType = value.GetType();
                    bsonWriter.WriteStartDocument();
                    bsonWriter.WriteString("_t", TypeNameDiscriminator.GetDiscriminator(actualType));
                    bsonWriter.WriteName("_v");
                    Serialize(bsonWriter, actualType, value, options);
                    bsonWriter.WriteEndDocument();
                    return;
                }

                var items = (Queue)value;
                var arraySerializationOptions = EnsureSerializationOptions<ArraySerializationOptions>(options);
                var itemSerializationOptions = arraySerializationOptions.ItemSerializationOptions;

                bsonWriter.WriteStartArray();
                foreach (var item in items)
                {
                    BsonSerializer.Serialize(bsonWriter, typeof(object), item, itemSerializationOptions);
                }
                bsonWriter.WriteEndArray();
            }
        }