/// <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 doubleValue = (double)value;
            var representationSerializationOptions = EnsureSerializationOptions<RepresentationSerializationOptions>(options);

            switch (representationSerializationOptions.Representation)
            {
                case BsonType.Double:
                    bsonWriter.WriteDouble(doubleValue);
                    break;
                case BsonType.Int32:
                    bsonWriter.WriteInt32(representationSerializationOptions.ToInt32(doubleValue));
                    break;
                case BsonType.Int64:
                    bsonWriter.WriteInt64(representationSerializationOptions.ToInt64(doubleValue));
                    break;
                case BsonType.String:
                    bsonWriter.WriteString(doubleValue.ToString("R", NumberFormatInfo.InvariantInfo));
                    break;
                default:
                    var message = string.Format("'{0}' is not a valid Double 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");
            }

            var bsonDouble = (BsonDouble)value;
            bsonWriter.WriteDouble(bsonDouble.Value);
        }
        /// <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 decimalValue = (Decimal)value;
            var representationSerializationOptions = EnsureSerializationOptions<RepresentationSerializationOptions>(options);

            switch (representationSerializationOptions.Representation)
            {
                case BsonType.Array:
                    bsonWriter.WriteStartArray();
                    var bits = Decimal.GetBits(decimalValue);
                    bsonWriter.WriteInt32(bits[0]);
                    bsonWriter.WriteInt32(bits[1]);
                    bsonWriter.WriteInt32(bits[2]);
                    bsonWriter.WriteInt32(bits[3]);
                    bsonWriter.WriteEndArray();
                    break;
                case BsonType.Double:
                    bsonWriter.WriteDouble(representationSerializationOptions.ToDouble(decimalValue));
                    break;
                case BsonType.Int32:
                    bsonWriter.WriteInt32(representationSerializationOptions.ToInt32(decimalValue));
                    break;
                case BsonType.Int64:
                    bsonWriter.WriteInt64(representationSerializationOptions.ToInt64(decimalValue));
                    break;
                case BsonType.String:
                    bsonWriter.WriteString(XmlConvert.ToString(decimalValue));
                    break;
                default:
                    var message = string.Format("'{0}' is not a valid Decimal 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)
        {
            var int64Value = (long)value;
            var representationSerializationOptions = EnsureSerializationOptions<RepresentationSerializationOptions>(options);

            switch (representationSerializationOptions.Representation)
            {
                case BsonType.Double:
                    bsonWriter.WriteDouble(representationSerializationOptions.ToDouble(int64Value));
                    break;
                case BsonType.Int32:
                    bsonWriter.WriteInt32(representationSerializationOptions.ToInt32(int64Value));
                    break;
                case BsonType.Int64:
                    bsonWriter.WriteInt64(int64Value);
                    break;
                case BsonType.String:
                    bsonWriter.WriteString(XmlConvert.ToString(int64Value));
                    break;
                default:
                    var message = string.Format("'{0}' is not a valid Int64 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)
        {
            var timeSpan = (TimeSpan)value;

            // support RepresentationSerializationOptions for backward compatibility
            var representationSerializationOptions = options as RepresentationSerializationOptions;
            if (representationSerializationOptions != null)
            {
                options = new TimeSpanSerializationOptions(representationSerializationOptions.Representation);
            }
            var timeSpanSerializationOptions = EnsureSerializationOptions<TimeSpanSerializationOptions>(options);

            if (timeSpanSerializationOptions.Representation == BsonType.String)
            {
                bsonWriter.WriteString(timeSpan.ToString()); // for TimeSpan use .NET's format instead of XmlConvert.ToString
            }
            else if (timeSpanSerializationOptions.Units == TimeSpanUnits.Ticks)
            {
                var ticks = timeSpan.Ticks;
                switch (timeSpanSerializationOptions.Representation)
                {
                    case BsonType.Double: bsonWriter.WriteDouble((double)ticks); break;
                    case BsonType.Int32: bsonWriter.WriteInt32((int)ticks); break;
                    case BsonType.Int64: bsonWriter.WriteInt64(ticks); break;
                    default:
                        var message = string.Format("'{0}' is not a valid TimeSpan representation.", timeSpanSerializationOptions.Representation);
                        throw new BsonSerializationException(message);
                }
            }
            else
            {
                double interval;
                switch (timeSpanSerializationOptions.Units)
                {
                    case TimeSpanUnits.Days: interval = timeSpan.TotalDays; break;
                    case TimeSpanUnits.Hours: interval = timeSpan.TotalHours; break;
                    case TimeSpanUnits.Minutes: interval = timeSpan.TotalMinutes; break;
                    case TimeSpanUnits.Seconds: interval = timeSpan.TotalSeconds; break;
                    case TimeSpanUnits.Milliseconds: interval = timeSpan.TotalMilliseconds; break;
                    case TimeSpanUnits.Nanoseconds: interval = timeSpan.TotalMilliseconds * 1000.0; break;
                    default:
                        var message = string.Format("'{0}' is not a valid TimeSpanUnits value.", timeSpanSerializationOptions.Units);
                        throw new BsonSerializationException(message);
                }

                switch (timeSpanSerializationOptions.Representation)
                {
                    case BsonType.Double: bsonWriter.WriteDouble(interval); break;
                    case BsonType.Int32: bsonWriter.WriteInt32((int)interval); break;
                    case BsonType.Int64: bsonWriter.WriteInt64((long)interval); break;
                    default:
                        var message = string.Format("'{0}' is not a valid TimeSpan representation.", timeSpanSerializationOptions.Representation);
                        throw new BsonSerializationException(message);
                }
            }
        }