// public methods
        /// <summary>
        /// Apply an attribute to these serialization options and modify the options accordingly.
        /// </summary>
        /// <param name="serializer">The serializer that these serialization options are for.</param>
        /// <param name="attribute">The serialization options attribute.</param>
        public override void ApplyAttribute(IBsonSerializer serializer, Attribute attribute)
        {
            EnsureNotFrozen();
            var representationAttribute = attribute as BsonRepresentationAttribute;

            if (representationAttribute != null)
            {
                _representation = representationAttribute.Representation;
                return;
            }

            var optionsAttribute = attribute as BsonTimeSpanOptionsAttribute;

            if (optionsAttribute != null)
            {
                _representation = optionsAttribute.Representation;
                _units          = optionsAttribute.Units;
                return;
            }

            var message = string.Format("A serialization options attribute of type {0} cannot be applied to serialization options of type {1}.",
                                        BsonUtils.GetFriendlyTypeName(attribute.GetType()), BsonUtils.GetFriendlyTypeName(GetType()));

            throw new NotSupportedException(message);
        }
 public void TestLessThanMinToDateTimeConversion()
 {
     var actual = BsonUtils.ToDateTimeFromMillisecondsSinceEpoch(
         BsonConstants.DateTimeMinValueMillisecondsSinceEpoch - 1);
 }
        /// <summary>
        /// Writes a BSON DateTime to the writer.
        /// </summary>
        /// <param name="value">The number of milliseconds since the Unix epoch.</param>
        public override void WriteDateTime(long value)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException("JsonWriter");
            }
            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
            {
                ThrowInvalidState("WriteDateTime", BsonWriterState.Value, BsonWriterState.Initial);
            }

            switch (_jsonWriterSettings.OutputMode)
            {
            case JsonOutputMode.Strict:
                WriteStartDocument();
                WriteInt64("$date", value);
                WriteEndDocument();
                break;

            case JsonOutputMode.JavaScript:
            case JsonOutputMode.TenGen:
                WriteNameHelper(Name);
                _textWriter.Write("new Date({0})", value);
                break;

            case JsonOutputMode.Shell:
                WriteNameHelper(Name);
                if (_jsonWriterSettings.ShellVersion >= new Version(1, 8, 0))
                {
                    // use ISODate for values that fall within .NET's DateTime range, and "new Date" for all others
                    if (value >= BsonConstants.DateTimeMinValueMillisecondsSinceEpoch &&
                        value <= BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch)
                    {
                        var utcDateTime = BsonUtils.ToDateTimeFromMillisecondsSinceEpoch(value);

                        if (!_jsonWriterSettings.UseIso8601DateFormat)
                        {
                            _textWriter.Write("ISODate(\"{0}\")", utcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.FFFZ"));
                        }
                        else
                        {
                            _textWriter.Write("\"{0}\"", utcDateTime.ToString("s", CultureInfo.InvariantCulture));
                        }
                    }
                    else
                    {
                        _textWriter.Write("new Date({0})", value);
                    }
                }
                else
                {
                    _textWriter.Write("new Date({0})", value);
                }
                break;

            default:
                throw new BsonInternalException("Unexpected JsonOutputMode.");
            }

            State = GetNextState();
        }
 public void TestToHexStringNull()
 {
     var actual = BsonUtils.ToHexString(null);
 }
 public void TestParseHexStringInvalid2()
 {
     var actual = BsonUtils.ParseHexString("00 1");
 }
 /// <summary>
 /// To the hex string.
 /// </summary>
 /// <param name="bytes">The bytes.</param>
 /// <returns></returns>
 protected string ToHexString(byte[] bytes)
 {
     return(BsonUtils.ToHexString(bytes));
 }
Esempio n. 7
0
        private void TranslateWithIndex(MethodCallExpression methodCallExpression)
        {
            if (methodCallExpression.Arguments.Count != 2)
            {
                throw new ArgumentOutOfRangeException("methodCallExpression");
            }

            var method = methodCallExpression.Method;

            if (method.DeclaringType != typeof(LinqToMongo))
            {
                var message = string.Format("WithIndex method of class {0} is not supported.", BsonUtils.GetFriendlyTypeName(method.DeclaringType));
                throw new NotSupportedException(message);
            }

            if (_indexHint != null)
            {
                throw new NotSupportedException("Only one index can be used for each query");
            }

            if (_distinct != null)
            {
                var message = "WithIndex cannot be used together with Distinct.";
                throw new NotSupportedException(message);
            }

            Expression expression = methodCallExpression.Arguments[1];

            if (expression.Type != typeof(BsonString) && expression.Type != typeof(BsonDocument))
            {
                throw new ArgumentOutOfRangeException("methodCallExpression", "Expected an Expression of Type BsonString or BsonDocument.");
            }

            var constantExpression = expression as ConstantExpression;

            if (constantExpression == null)
            {
                throw new ArgumentOutOfRangeException("methodCallExpression", "Expected a ConstantExpression.");
            }

            _indexHint = (BsonValue)constantExpression.Value;
        }
Esempio n. 8
0
        /// <summary>
        /// Gets the serializer.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public override IBsonSerializer GetSerializer(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            if (type.IsGenericType && type.ContainsGenericParameters)
            {
                var message = string.Format("Generic type {0} has unassigned type parameters.", BsonUtils.GetFriendlyTypeName(type));
                throw new ArgumentException(message, "type");
            }

            if (type.IsInterface)
            {
                var serializerTypeDefinition = typeof(DiscriminatedInterfaceSerializer <>);
                return(CreateGenericSerializer(serializerTypeDefinition, type));
            }

            return(null);
        }
Esempio n. 9
0
        /// <summary>
        /// Registers a serializer for a type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="serializer">The serializer.</param>
        public static void RegisterSerializer(Type type, IBsonSerializer serializer)
        {
            if (typeof(IBsonSerializable).IsAssignableFrom(type))
            {
                var message = string.Format("A serializer cannot be registered for type {0} because it implements IBsonSerializable.", BsonUtils.GetFriendlyTypeName(type));
                throw new BsonSerializationException(message);
            }

            __configLock.EnterWriteLock();
            try
            {
                if (__serializers.ContainsKey(type))
                {
                    var message = string.Format("There is already a serializer registered for type {0}.", type.FullName);
                    throw new BsonSerializationException(message);
                }
                __serializers.Add(type, serializer);
            }
            finally
            {
                __configLock.ExitWriteLock();
            }
        }
        // public methods
        /// <summary>
        /// Apply an attribute to these serialization options and modify the options accordingly.
        /// </summary>
        /// <param name="serializer">The serializer that these serialization options are for.</param>
        /// <param name="attribute">The serialization options attribute.</param>
        public override void ApplyAttribute(IBsonSerializer serializer, Attribute attribute)
        {
            EnsureNotFrozen();
            var message = string.Format("A serialization options attribute of type {0} cannot be applied to serialization options of type {1}.",
                                        BsonUtils.GetFriendlyTypeName(attribute.GetType()), BsonUtils.GetFriendlyTypeName(GetType()));

            throw new NotSupportedException(message);
        }
        /// <summary>
        /// Gets a serializer for a type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>
        /// A serializer.
        /// </returns>
        public override IBsonSerializer GetSerializer(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            if (type.IsGenericType && type.ContainsGenericParameters)
            {
                var message = string.Format("Generic type {0} has unassigned type parameters.", BsonUtils.GetFriendlyTypeName(type));
                throw new ArgumentException(message, "type");
            }

            Type serializerType;

            if (__serializersTypes.TryGetValue(type, out serializerType))
            {
                return(CreateSerializer(serializerType));
            }

            if (type.IsGenericType && !type.ContainsGenericParameters)
            {
                Type serializerTypeDefinition;
                if (__serializersTypes.TryGetValue(type.GetGenericTypeDefinition(), out serializerTypeDefinition))
                {
                    return(CreateGenericSerializer(serializerTypeDefinition, type.GetGenericArguments()));
                }
            }

            if (type.IsEnum)
            {
                return(CreateGenericSerializer(typeof(EnumSerializer <>), type));
            }

            return(null);
        }
Esempio n. 12
0
        /// <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 <TKey, TValue>)value;
                var dictionarySerializationOptions   = EnsureSerializationOptions(options);
                var dictionaryRepresentation         = dictionarySerializationOptions.Representation;
                var keyValuePairSerializationOptions = dictionarySerializationOptions.KeyValuePairSerializationOptions;

                if (dictionaryRepresentation == DictionaryRepresentation.Dynamic)
                {
                    if (typeof(TKey) == typeof(string) || typeof(TKey) == typeof(object))
                    {
                        dictionaryRepresentation = DictionaryRepresentation.Document;
                        foreach (object key in dictionary.Keys)
                        {
                            var name = key as string; // key might not be a string
                            if (name == null || (name.Length > 0 && name[0] == '$') || name.IndexOf('.') != -1)
                            {
                                dictionaryRepresentation = DictionaryRepresentation.ArrayOfArrays;
                                break;
                            }
                        }
                    }
                    else
                    {
                        dictionaryRepresentation = DictionaryRepresentation.ArrayOfArrays;
                    }
                }

                switch (dictionaryRepresentation)
                {
                case DictionaryRepresentation.Document:
                    bsonWriter.WriteStartDocument();
                    foreach (var keyValuePair in dictionary)
                    {
                        bsonWriter.WriteName((string)(object)keyValuePair.Key);
                        BsonSerializer.Serialize(bsonWriter, typeof(TValue), keyValuePair.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 (var keyValuePair in dictionary)
                    {
                        _keyValuePairSerializer.Serialize(
                            bsonWriter,
                            typeof(KeyValuePair <TKey, TValue>),
                            keyValuePair,
                            keyValuePairSerializationOptions);
                    }
                    bsonWriter.WriteEndArray();
                    break;

                default:
                    var message = string.Format("'{0}' is not a valid IDictionary<{1}, {2}> representation.",
                                                dictionaryRepresentation,
                                                BsonUtils.GetFriendlyTypeName(typeof(TKey)),
                                                BsonUtils.GetFriendlyTypeName(typeof(TValue)));
                    throw new BsonSerializationException(message);
                }
            }
        }
Esempio n. 13
0
        /*******************************************/

        public override DataTable Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            var bsonReader = context.Reader;

            var bsonType = bsonReader.CurrentBsonType;

            if (bsonReader.State != BsonReaderState.Type)
            {
                bsonType = bsonReader.GetCurrentBsonType();
            }

            string message;

            switch (bsonType)
            {
            case BsonType.Array:
                bsonReader.ReadStartArray();

                DataTable table = new DataTable();

                bool initialised = false;

                while (bsonReader.State != BsonReaderState.EndOfArray && bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    Dictionary <string, object> rowData = BsonSerializer.Deserialize <Dictionary <string, object> >(bsonReader);
                    if (!initialised)
                    {
                        foreach (var kvp in rowData)
                        {
                            table.Columns.Add(new DataColumn(kvp.Key, kvp.Value.GetType()));
                        }
                        initialised = true;
                    }

                    DataRow row = table.NewRow();

                    foreach (var kvp in rowData)
                    {
                        row[kvp.Key] = kvp.Value;
                    }
                    table.Rows.Add(row);
                }

                bsonReader.ReadEndArray();

                return(table);

            default:
                message = string.Format("Cannot deserialize a '{0}' from BsonType '{1}'.", BsonUtils.GetFriendlyTypeName(typeof(DataTable)), bsonType);
                throw new FormatException(message);
            }
        }
        // public methods
        /// <summary>
        /// Apply an attribute to these serialization options and modify the options accordingly.
        /// </summary>
        /// <param name="serializer">The serializer that these serialization options are for.</param>
        /// <param name="attribute">The serialization options attribute.</param>
        public override void ApplyAttribute(IBsonSerializer serializer, Attribute attribute)
        {
            EnsureNotFrozen();

            var dictionaryOptionsAttribute = attribute as BsonDictionaryOptionsAttribute;

            if (dictionaryOptionsAttribute != null)
            {
                _representation = dictionaryOptionsAttribute.Representation;
                return;
            }

            // for backward compatibility reasons representations Array and Document apply to the Dictionary and not the values
            var representationAttribute = attribute as BsonRepresentationAttribute;

            if (representationAttribute != null)
            {
                switch (representationAttribute.Representation)
                {
                case BsonType.Array:
                    _representation = DictionaryRepresentation.ArrayOfArrays;
                    return;

                case BsonType.Document:
                    _representation = DictionaryRepresentation.Document;
                    return;
                }
            }

            // any other attributes are applied to the values
            var valueType = typeof(object);

            if (serializer.GetType().IsGenericType)
            {
                valueType = serializer.GetType().GetGenericArguments()[1]; // TValue
            }
            var valueSerializer = BsonSerializer.LookupSerializer(valueType);

            var valueSerializationOptions = _keyValuePairSerializationOptions.ValueSerializationOptions;

            if (valueSerializationOptions == null)
            {
                var valueDefaultSerializationOptions = valueSerializer.GetDefaultSerializationOptions();

                // special case for legacy dictionaries: allow BsonRepresentation on object
                if (valueDefaultSerializationOptions == null &&
                    serializer.GetType() == typeof(DictionarySerializer) &&
                    attribute.GetType() == typeof(BsonRepresentationAttribute))
                {
                    valueDefaultSerializationOptions = new RepresentationSerializationOptions(BsonType.Null); // will be modified later by ApplyAttribute
                }

                if (valueDefaultSerializationOptions == null)
                {
                    var message = string.Format(
                        "A serialization options attribute of type {0} cannot be used when the serializer is of type {1} and the value serializer is of type {2}.",
                        BsonUtils.GetFriendlyTypeName(attribute.GetType()),
                        BsonUtils.GetFriendlyTypeName(serializer.GetType()),
                        BsonUtils.GetFriendlyTypeName(valueSerializer.GetType()));
                    throw new NotSupportedException(message);
                }

                valueSerializationOptions = valueDefaultSerializationOptions.Clone();
            }

            valueSerializationOptions.ApplyAttribute(valueSerializer, attribute);
            _keyValuePairSerializationOptions = new KeyValuePairSerializationOptions(
                _keyValuePairSerializationOptions.Representation,
                _keyValuePairSerializationOptions.KeySerializationOptions,
                valueSerializationOptions);
        }
Esempio n. 15
0
        // public methods
        /// <summary>
        /// Deserializes an object from a BsonReader.
        /// </summary>
        /// <param name="bsonReader">The BsonReader.</param>
        /// <param name="nominalType">The nominal type of the object.</param>
        /// <param name="actualType">The actual type of the object.</param>
        /// <param name="options">The serialization options.</param>
        /// <returns>An object.</returns>
        public override object Deserialize(
            BsonReader bsonReader,
            Type nominalType,
            Type actualType,
            IBsonSerializationOptions options)
        {
            VerifyTypes(nominalType, actualType, typeof(SystemProfileInfo));

            if (bsonReader.GetCurrentBsonType() == Bson.BsonType.Null)
            {
                bsonReader.ReadNull();
                return(null);
            }
            else
            {
                var profileInfo = new SystemProfileInfo();

                bsonReader.ReadStartDocument();
                BsonType bsonType;
                while ((bsonType = bsonReader.ReadBsonType()) != BsonType.EndOfDocument)
                {
                    var name = bsonReader.ReadName();
                    switch (name)
                    {
                    case "abbreviated":
                        profileInfo.Abbreviated = bsonReader.ReadString();
                        break;

                    case "client":
                        profileInfo.Client = bsonReader.ReadString();
                        break;

                    case "command":
                        profileInfo.Command = BsonDocument.ReadFrom(bsonReader);
                        break;

                    case "cursorid":
                        profileInfo.CursorId = BsonValue.ReadFrom(bsonReader).ToInt64();
                        break;

                    case "err":
                        profileInfo.Error = bsonReader.ReadString();
                        break;

                    case "exception":
                        profileInfo.Exception = bsonReader.ReadString();
                        break;

                    case "exceptionCode":
                        profileInfo.ExceptionCode = BsonValue.ReadFrom(bsonReader).ToInt32();
                        break;

                    case "exhaust":
                        profileInfo.Exhaust = BsonValue.ReadFrom(bsonReader).ToBoolean();
                        break;

                    case "fastmod":
                        profileInfo.FastMod = BsonValue.ReadFrom(bsonReader).ToBoolean();
                        break;

                    case "fastmodinsert":
                        profileInfo.FastModInsert = BsonValue.ReadFrom(bsonReader).ToBoolean();
                        break;

                    case "idhack":
                        profileInfo.IdHack = BsonValue.ReadFrom(bsonReader).ToBoolean();
                        break;

                    case "info":
                        profileInfo.Info = bsonReader.ReadString();
                        break;

                    case "keyUpdates":
                        profileInfo.KeyUpdates = BsonValue.ReadFrom(bsonReader).ToInt32();
                        break;

                    case "millis":
                        profileInfo.Duration = TimeSpan.FromMilliseconds(BsonValue.ReadFrom(bsonReader).ToDouble());
                        break;

                    case "moved":
                        profileInfo.Moved = BsonValue.ReadFrom(bsonReader).ToBoolean();
                        break;

                    case "nreturned":
                        profileInfo.NumberReturned = BsonValue.ReadFrom(bsonReader).ToInt32();
                        break;

                    case "ns":
                        profileInfo.Namespace = bsonReader.ReadString();
                        break;

                    case "nscanned":
                        profileInfo.NumberScanned = BsonValue.ReadFrom(bsonReader).ToInt32();
                        break;

                    case "ntoreturn":
                        profileInfo.NumberToReturn = BsonValue.ReadFrom(bsonReader).ToInt32();
                        break;

                    case "ntoskip":
                        profileInfo.NumberToSkip = BsonValue.ReadFrom(bsonReader).ToInt32();
                        break;

                    case "op":
                        profileInfo.Op = bsonReader.ReadString();
                        break;

                    case "query":
                        profileInfo.Query = BsonDocument.ReadFrom(bsonReader);
                        break;

                    case "responseLength":
                        profileInfo.ResponseLength = BsonValue.ReadFrom(bsonReader).ToInt32();
                        break;

                    case "scanAndOrder":
                        profileInfo.ScanAndOrder = BsonValue.ReadFrom(bsonReader).ToBoolean();
                        break;

                    case "ts":
                        profileInfo.Timestamp = BsonUtils.ToDateTimeFromMillisecondsSinceEpoch(bsonReader.ReadDateTime());
                        break;

                    case "updateobj":
                        profileInfo.UpdateObject = BsonDocument.ReadFrom(bsonReader);
                        break;

                    case "upsert":
                        profileInfo.Upsert = BsonValue.ReadFrom(bsonReader).ToBoolean();
                        break;

                    case "user":
                        profileInfo.User = bsonReader.ReadString();
                        break;

                    default:
                        break;     // ignore unknown elements
                    }
                }
                bsonReader.ReadEndDocument();

                return(profileInfo);
            }
        }
Esempio n. 16
0
        /// <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();
        }
Esempio n. 17
0
        /// <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 profileInfo = (SystemProfileInfo)value;

                bsonWriter.WriteStartDocument();
                bsonWriter.WriteDateTime("ts", BsonUtils.ToMillisecondsSinceEpoch(profileInfo.Timestamp));
                if (profileInfo.Info != null)
                {
                    bsonWriter.WriteString("info", profileInfo.Info);
                }
                if (profileInfo.Op != null)
                {
                    bsonWriter.WriteString("op", profileInfo.Op);
                }
                if (profileInfo.Namespace != null)
                {
                    bsonWriter.WriteString("ns", profileInfo.Namespace);
                }
                if (profileInfo.Command != null)
                {
                    bsonWriter.WriteName("command");
                    profileInfo.Command.WriteTo(bsonWriter);
                }
                if (profileInfo.Query != null)
                {
                    bsonWriter.WriteName("query");
                    profileInfo.Query.WriteTo(bsonWriter);
                }
                if (profileInfo.UpdateObject != null)
                {
                    bsonWriter.WriteName("updateobj");
                    profileInfo.UpdateObject.WriteTo(bsonWriter);
                }
                if (profileInfo.CursorId != 0)
                {
                    bsonWriter.WriteInt64("cursorid", profileInfo.CursorId);
                }
                if (profileInfo.NumberToReturn != 0)
                {
                    bsonWriter.WriteInt32("ntoreturn", profileInfo.NumberToReturn);
                }
                if (profileInfo.NumberToSkip != 0)
                {
                    bsonWriter.WriteInt32("ntoskip", profileInfo.NumberToSkip);
                }
                if (profileInfo.Exhaust)
                {
                    bsonWriter.WriteBoolean("exhaust", profileInfo.Exhaust);
                }
                if (profileInfo.NumberScanned != 0)
                {
                    bsonWriter.WriteInt32("nscanned", profileInfo.NumberScanned);
                }
                if (profileInfo.IdHack)
                {
                    bsonWriter.WriteBoolean("idhack", profileInfo.IdHack);
                }
                if (profileInfo.ScanAndOrder)
                {
                    bsonWriter.WriteBoolean("scanAndOrder", profileInfo.ScanAndOrder);
                }
                if (profileInfo.Moved)
                {
                    bsonWriter.WriteBoolean("moved", profileInfo.Moved);
                }
                if (profileInfo.FastMod)
                {
                    bsonWriter.WriteBoolean("fastmod", profileInfo.FastMod);
                }
                if (profileInfo.FastModInsert)
                {
                    bsonWriter.WriteBoolean("fastmodinsert", profileInfo.FastModInsert);
                }
                if (profileInfo.Upsert)
                {
                    bsonWriter.WriteBoolean("upsert", profileInfo.Upsert);
                }
                if (profileInfo.KeyUpdates != 0)
                {
                    bsonWriter.WriteInt32("keyUpdates", profileInfo.KeyUpdates);
                }
                if (profileInfo.Exception != null)
                {
                    bsonWriter.WriteString("exception", profileInfo.Exception);
                }
                if (profileInfo.ExceptionCode != 0)
                {
                    bsonWriter.WriteInt32("exceptionCode", profileInfo.ExceptionCode);
                }
                if (profileInfo.NumberReturned != 0)
                {
                    bsonWriter.WriteInt32("nreturned", profileInfo.NumberReturned);
                }
                if (profileInfo.ResponseLength != 0)
                {
                    bsonWriter.WriteInt32("responseLength", profileInfo.ResponseLength);
                }
                bsonWriter.WriteDouble("millis", profileInfo.Duration.TotalMilliseconds);
                if (profileInfo.Client != null)
                {
                    bsonWriter.WriteString("client", profileInfo.Client);
                }
                if (profileInfo.User != null)
                {
                    bsonWriter.WriteString("user", profileInfo.User);
                }
                if (profileInfo.Error != null)
                {
                    bsonWriter.WriteString("err", profileInfo.Error);
                }
                if (profileInfo.Abbreviated != null)
                {
                    bsonWriter.WriteString("abbreviated", profileInfo.Abbreviated);
                }
                bsonWriter.WriteEndDocument();
            }
        }
        /// <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, object value)
        {
            var bsonWriter = context.Writer;

            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                var actualType = value.GetType();
                if (actualType == typeof(object))
                {
                    bsonWriter.WriteStartDocument();
                    bsonWriter.WriteEndDocument();
                }
                else
                {
                    // certain types can be written directly as BSON value
                    // if we're not at the top level document, or if we're using the JsonWriter
                    if (bsonWriter.State == BsonWriterState.Value || bsonWriter is JsonWriter)
                    {
                        switch (Type.GetTypeCode(actualType))
                        {
                        case TypeCode.Boolean:
                            bsonWriter.WriteBoolean((bool)value);
                            return;

                        case TypeCode.DateTime:
                            // TODO: is this right? will lose precision after round trip
                            var bsonDateTime = new BsonDateTime(BsonUtils.ToUniversalTime((DateTime)value));
                            bsonWriter.WriteDateTime(bsonDateTime.MillisecondsSinceEpoch);
                            return;

                        case TypeCode.Double:
                            bsonWriter.WriteDouble((double)value);
                            return;

                        case TypeCode.Int16:
                            // TODO: is this right? will change type to Int32 after round trip
                            bsonWriter.WriteInt32((short)value);
                            return;

                        case TypeCode.Int32:
                            bsonWriter.WriteInt32((int)value);
                            return;

                        case TypeCode.Int64:
                            bsonWriter.WriteInt64((long)value);
                            return;

                        case TypeCode.Object:
                            if (actualType == typeof(Decimal128))
                            {
                                var decimal128 = (Decimal128)value;
                                bsonWriter.WriteDecimal128(decimal128);
                                return;
                            }
                            if (actualType == typeof(Guid))
                            {
                                var guid = (Guid)value;
                                var guidRepresentation = bsonWriter.Settings.GuidRepresentation;
                                var binaryData         = new BsonBinaryData(guid, guidRepresentation);
                                bsonWriter.WriteBinaryData(binaryData);
                                return;
                            }
                            if (actualType == typeof(ObjectId))
                            {
                                bsonWriter.WriteObjectId((ObjectId)value);
                                return;
                            }
                            break;

                        case TypeCode.String:
                            bsonWriter.WriteString((string)value);
                            return;
                        }
                    }

                    SerializeDiscriminatedValue(context, args, value, actualType);
                }
            }
        }
Esempio n. 19
0
        private void TranslateOfType(MethodCallExpression methodCallExpression)
        {
            var method = methodCallExpression.Method;

            if (method.DeclaringType != typeof(Queryable))
            {
                var message = string.Format("OfType method of class {0} is not supported.", BsonUtils.GetFriendlyTypeName(method.DeclaringType));
                throw new NotSupportedException(message);
            }
            if (!method.IsStatic)
            {
                throw new NotSupportedException("Expected OfType to be a static method.");
            }
            if (!method.IsGenericMethod)
            {
                throw new NotSupportedException("Expected OfType to be a generic method.");
            }
            var actualType = method.GetGenericArguments()[0];

            var args = methodCallExpression.Arguments.ToArray();

            if (args.Length != 1)
            {
                throw new NotSupportedException("Expected OfType method to have a single argument.");
            }
            var sourceExpression         = args[0];
            var sourceExpressionTypeInfo = sourceExpression.Type.GetTypeInfo();

            if (!sourceExpressionTypeInfo.IsGenericType)
            {
                throw new NotSupportedException("Expected source argument to OfType to be a generic type.");
            }
            var nominalType = sourceExpressionTypeInfo.GetGenericArguments()[0];

            if (_projection != null)
            {
                throw new NotSupportedException("OfType after a projection is not supported.");
            }

            var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(nominalType);
            var discriminator           = discriminatorConvention.GetDiscriminator(nominalType, actualType);

            if (discriminator == null)
            {
                return; // nothing to do
            }

            if (discriminator.IsBsonArray)
            {
                discriminator = discriminator[discriminator.AsBsonArray.Count - 1];
            }
            var query = Query.EQ(discriminatorConvention.ElementName, discriminator);

            var injectMethodInfo = typeof(LinqToMongo).GetMethod("Inject");
            var body             = Expression.Call(injectMethodInfo, Expression.Constant(query));
            var parameter        = Expression.Parameter(nominalType, "x");
            var predicate        = Expression.Lambda(body, parameter);

            CombinePredicateWithWhereClause(methodCallExpression, predicate);

            _ofType = actualType;
        }
        // public methods
        /// <summary>
        /// Deserializes a value.
        /// </summary>
        /// <param name="context">The deserialization context.</param>
        /// <returns>An object.</returns>
        public override DateTime Deserialize(BsonDeserializationContext context)
        {
            var      bsonReader = context.Reader;
            DateTime value;

            var bsonType = bsonReader.GetCurrentBsonType();

            switch (bsonType)
            {
            case BsonType.DateTime:
                // use an intermediate BsonDateTime so MinValue and MaxValue are handled correctly
                value = new BsonDateTime(bsonReader.ReadDateTime()).ToUniversalTime();
                break;

            case BsonType.Document:
                value = default(DateTime);
                _helper.DeserializeMembers(context, (elementName, flag) =>
                {
                    switch (flag)
                    {
                    case Flags.DateTime: bsonReader.SkipValue(); break;         // ignore value (use Ticks instead)

                    case Flags.Ticks: value = new DateTime(context.DeserializeWithChildContext(_int64Serializer), DateTimeKind.Utc); break;
                    }
                });
                break;

            case BsonType.Int64:
                value = DateTime.SpecifyKind(new DateTime(bsonReader.ReadInt64()), DateTimeKind.Utc);
                break;

            case BsonType.String:
                if (_dateOnly)
                {
                    value = DateTime.SpecifyKind(DateTime.ParseExact(bsonReader.ReadString(), "yyyy-MM-dd", null), DateTimeKind.Utc);
                }
                else
                {
                    value = JsonConvert.ToDateTime(bsonReader.ReadString());
                }
                break;

            default:
                throw CreateCannotDeserializeFromBsonTypeException(bsonType);
            }

            if (_dateOnly)
            {
                if (value.TimeOfDay != TimeSpan.Zero)
                {
                    throw new FormatException("TimeOfDay component for DateOnly DateTime value is not zero.");
                }
                value = DateTime.SpecifyKind(value, _kind); // not ToLocalTime or ToUniversalTime!
            }
            else
            {
                switch (_kind)
                {
                case DateTimeKind.Local:
                case DateTimeKind.Unspecified:
                    value = DateTime.SpecifyKind(BsonUtils.ToLocalTime(value), _kind);
                    break;

                case DateTimeKind.Utc:
                    value = BsonUtils.ToUniversalTime(value);
                    break;
                }
            }

            return(value);
        }
Esempio n. 21
0
        /// <summary>
        /// Uploads a GridFS file.
        /// </summary>
        /// <param name="stream">The source stream.</param>
        /// <param name="remoteFileName">The remote file name.</param>
        /// <param name="createOptions">The create options.</param>
        /// <returns>The file info of the new GridFS file.</returns>
        public MongoGridFSFileInfo Upload(
            Stream stream,
            string remoteFileName,
            MongoGridFSCreateOptions createOptions)
        {
            if (_settings.ReadPreference != ReadPreference.Primary)
            {
                var gridFS = WithReadPreferencePrimary();
                return(gridFS.Upload(stream, remoteFileName, createOptions));
            }
            using (_server.RequestStart(ReadPreference.Primary))
            {
                var connectionId = _server.RequestConnectionId;
                EnsureIndexes();

                var database         = GetDatabase(ReadPreference.Primary);
                var chunksCollection = GetChunksCollection(database);
                var filesCollection  = GetFilesCollection(database);

                var files_id  = createOptions.Id ?? ObjectId.GenerateNewId();
                var chunkSize = (createOptions.ChunkSize == 0) ? _settings.ChunkSize : createOptions.ChunkSize;
                var buffer    = new byte[chunkSize];

                var    length    = 0L;
                string md5Client = null;
                using (var md5Algorithm = _settings.VerifyMD5 ? MD5.Create() : null)
                {
                    for (var n = 0L; true; n++)
                    {
                        // might have to call Stream.Read several times to get a whole chunk
                        var bytesNeeded = chunkSize;
                        var bytesRead   = 0;
                        while (bytesNeeded > 0)
                        {
                            var partialRead = stream.Read(buffer, bytesRead, bytesNeeded);
                            if (partialRead == 0)
                            {
                                break; // EOF may or may not have a partial chunk
                            }
                            bytesNeeded -= partialRead;
                            bytesRead   += partialRead;
                        }
                        if (bytesRead == 0)
                        {
                            break; // EOF no partial chunk
                        }
                        length += bytesRead;

                        byte[] data = buffer;
                        if (bytesRead < chunkSize)
                        {
                            data = new byte[bytesRead];
                            Buffer.BlockCopy(buffer, 0, data, 0, bytesRead);
                        }

                        var chunk = new BsonDocument
                        {
                            { "_id", ObjectId.GenerateNewId() },
                            { "files_id", files_id },
                            { "n", n < int.MaxValue ? (BsonValue)(BsonInt32)(int)n : (BsonInt64)n },
                            { "data", new BsonBinaryData(data) }
                        };
                        chunksCollection.Insert(chunk, _settings.WriteConcern);

                        if (_settings.VerifyMD5)
                        {
                            md5Algorithm.TransformBlock(data, 0, data.Length, null, 0);
                        }

                        if (bytesRead < chunkSize)
                        {
                            break; // EOF after partial chunk
                        }
                    }

                    if (_settings.VerifyMD5)
                    {
                        md5Algorithm.TransformFinalBlock(new byte[0], 0, 0);
                        md5Client = BsonUtils.ToHexString(md5Algorithm.Hash);
                    }
                }

                string md5Server = null;
                if (_settings.UpdateMD5 || _settings.VerifyMD5)
                {
                    var md5Command = new CommandDocument
                    {
                        { "filemd5", files_id },
                        { "root", _settings.Root }
                    };
                    var md5Result = database.RunCommand(md5Command);
                    md5Server = md5Result.Response["md5"].AsString;
                }

                if (_settings.VerifyMD5 && !md5Client.Equals(md5Server, StringComparison.OrdinalIgnoreCase))
                {
                    throw new MongoGridFSException(connectionId, "Upload client and server MD5 hashes are not equal.");
                }

                var          uploadDate = (createOptions.UploadDate == DateTime.MinValue) ? DateTime.UtcNow : createOptions.UploadDate;
                var          aliases    = (createOptions.Aliases != null) ? new BsonArray(createOptions.Aliases) : null;
                BsonDocument fileInfo   = new BsonDocument
                {
                    { "_id", files_id },
                    { "filename", remoteFileName, !string.IsNullOrEmpty(remoteFileName) }, // optional
                    { "length", length },
                    { "chunkSize", chunkSize },
                    { "uploadDate", uploadDate },
                    { "md5", (md5Server == null) ? (BsonValue)BsonNull.Value : new BsonString(md5Server) },
                    { "contentType", createOptions.ContentType, !string.IsNullOrEmpty(createOptions.ContentType) }, // optional
                    { "aliases", aliases, aliases != null },                                                        // optional
                    { "metadata", createOptions.Metadata, createOptions.Metadata != null } // optional
                };
                filesCollection.Insert(fileInfo, _settings.WriteConcern);

                return(FindOneById(files_id));
            }
        }
        /// <summary>
        /// Serializes a value.
        /// </summary>
        /// <param name="context">The serialization context.</param>
        /// <param name="value">The object.</param>
        public override void Serialize(BsonSerializationContext context, DateTime value)
        {
            var bsonWriter = context.Writer;

            DateTime utcDateTime;

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

            switch (_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 (_dateOnly)
                {
                    bsonWriter.WriteString(value.ToString("yyyy-MM-dd"));
                }
                else
                {
                    if (value == DateTime.MinValue || value == DateTime.MaxValue)
                    {
                        // serialize MinValue and MaxValue as Unspecified so we do NOT get the time zone offset
                        value = DateTime.SpecifyKind(value, DateTimeKind.Unspecified);
                    }
                    else if (value.Kind == DateTimeKind.Unspecified)
                    {
                        // serialize Unspecified as Local se we get the time zone offset
                        value = DateTime.SpecifyKind(value, DateTimeKind.Local);
                    }
                    bsonWriter.WriteString(JsonConvert.ToString(value));
                }
                break;

            default:
                var message = string.Format("'{0}' is not a valid DateTime representation.", _representation);
                throw new BsonSerializationException(message);
            }
        }
 public void TestParseHexStringNull()
 {
     var actual = BsonUtils.ParseHexString(null);
 }
Esempio n. 24
0
        // public methods
        /// <summary>
        /// Deserializes an object from a BsonReader.
        /// </summary>
        /// <param name="bsonReader">The BsonReader.</param>
        /// <param name="nominalType">The nominal type of the object.</param>
        /// <param name="actualType">The actual type of the object.</param>
        /// <param name="options">The serialization options.</param>
        /// <returns>An object.</returns>
        public override object Deserialize(
            BsonReader bsonReader,
            Type nominalType,
            Type actualType,
            IBsonSerializationOptions options)
        {
            VerifyTypes(nominalType, actualType, typeof(DateTime));
            var dateTimeSerializationOptions = EnsureSerializationOptions <DateTimeSerializationOptions>(options);

            var      bsonType = bsonReader.GetCurrentBsonType();
            DateTime value;

            switch (bsonType)
            {
            case BsonType.DateTime:
                // use an intermediate BsonDateTime so MinValue and MaxValue are handled correctly
                value = BsonDateTime.Create(bsonReader.ReadDateTime()).Value;
                break;

            case BsonType.Document:
                bsonReader.ReadStartDocument();
                bsonReader.ReadDateTime("DateTime");     // ignore value (use Ticks instead)
                value = new DateTime(bsonReader.ReadInt64("Ticks"), DateTimeKind.Utc);
                bsonReader.ReadEndDocument();
                break;

            case BsonType.Int64:
                value = DateTime.SpecifyKind(new DateTime(bsonReader.ReadInt64()), DateTimeKind.Utc);
                break;

            case BsonType.String:
                // note: we're not using XmlConvert because of bugs in Mono
                if (dateTimeSerializationOptions.DateOnly)
                {
                    value = DateTime.SpecifyKind(DateTime.ParseExact(bsonReader.ReadString(), "yyyy-MM-dd", null), DateTimeKind.Utc);
                }
                else
                {
                    var formats = new string[] { "yyyy-MM-ddK", "yyyy-MM-ddTHH:mm:ssK", "yyyy-MM-ddTHH:mm:ss.FFFFFFFK" };
                    value = DateTime.ParseExact(bsonReader.ReadString(), formats, null, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
                }
                break;

            default:
                var message = string.Format("Cannot deserialize DateTime from BsonType {0}.", bsonType);
                throw new FileFormatException(message);
            }

            if (dateTimeSerializationOptions.DateOnly)
            {
                if (value.TimeOfDay != TimeSpan.Zero)
                {
                    throw new FileFormatException("TimeOfDay component for DateOnly DateTime value is not zero.");
                }
                value = DateTime.SpecifyKind(value, dateTimeSerializationOptions.Kind); // not ToLocalTime or ToUniversalTime!
            }
            else
            {
                switch (dateTimeSerializationOptions.Kind)
                {
                case DateTimeKind.Local:
                case DateTimeKind.Unspecified:
                    value = DateTime.SpecifyKind(BsonUtils.ToLocalTime(value), dateTimeSerializationOptions.Kind);
                    break;

                case DateTimeKind.Utc:
                    value = BsonUtils.ToUniversalTime(value);
                    break;
                }
            }

            return(value);
        }
 public void TestGreaterThanMaxToDateTimeConversion()
 {
     var actual = BsonUtils.ToDateTimeFromMillisecondsSinceEpoch(
         BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch + 1);
 }
Esempio n. 26
0
        /// <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);
            }
        }
        public void TestMinToMillisConversion()
        {
            var actual = BsonUtils.ToMillisecondsSinceEpoch(DateTime.MinValue);

            Assert.AreEqual(BsonConstants.DateTimeMinValueMillisecondsSinceEpoch, actual);
        }
Esempio n. 28
0
        /// <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;
                }

                // support RepresentationSerializationOptions for backward compatibility
                var representationSerializationOptions = options as RepresentationSerializationOptions;
                if (representationSerializationOptions != null)
                {
                    switch (representationSerializationOptions.Representation)
                    {
                    case BsonType.Array:
                        options = DictionarySerializationOptions.ArrayOfArrays;
                        break;

                    case BsonType.Document:
                        options = DictionarySerializationOptions.Document;
                        break;

                    default:
                        var message = string.Format("BsonType {0} is not a valid representation for a Dictionary.", representationSerializationOptions.Representation);
                        throw new BsonSerializationException(message);
                    }
                }

                var dictionary = (IDictionary <TKey, TValue>)value;
                var dictionarySerializationOptions = EnsureSerializationOptions <DictionarySerializationOptions>(options);
                var representation           = dictionarySerializationOptions.Representation;
                var itemSerializationOptions = dictionarySerializationOptions.ItemSerializationOptions;

                if (representation == DictionaryRepresentation.Dynamic)
                {
                    if (typeof(TKey) == typeof(string) || typeof(TKey) == typeof(object))
                    {
                        representation = 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)
                            {
                                representation = DictionaryRepresentation.ArrayOfArrays;
                                break;
                            }
                        }
                    }
                    else
                    {
                        representation = DictionaryRepresentation.ArrayOfArrays;
                    }
                }

                switch (representation)
                {
                case DictionaryRepresentation.Document:
                    bsonWriter.WriteStartDocument();
                    foreach (KeyValuePair <TKey, TValue> entry in dictionary)
                    {
                        bsonWriter.WriteName((string)(object)entry.Key);
                        BsonSerializer.Serialize(bsonWriter, typeof(TValue), entry.Value, itemSerializationOptions);
                    }
                    bsonWriter.WriteEndDocument();
                    break;

                case DictionaryRepresentation.ArrayOfArrays:
                    bsonWriter.WriteStartArray();
                    foreach (KeyValuePair <TKey, TValue> entry in dictionary)
                    {
                        bsonWriter.WriteStartArray();
                        BsonSerializer.Serialize(bsonWriter, typeof(TKey), entry.Key);
                        BsonSerializer.Serialize(bsonWriter, typeof(TValue), entry.Value, itemSerializationOptions);
                        bsonWriter.WriteEndArray();
                    }
                    bsonWriter.WriteEndArray();
                    break;

                case DictionaryRepresentation.ArrayOfDocuments:
                    bsonWriter.WriteStartArray();
                    foreach (KeyValuePair <TKey, TValue> entry in dictionary)
                    {
                        bsonWriter.WriteStartDocument();
                        bsonWriter.WriteName("k");
                        BsonSerializer.Serialize(bsonWriter, typeof(TKey), entry.Key);
                        bsonWriter.WriteName("v");
                        BsonSerializer.Serialize(bsonWriter, typeof(TValue), entry.Value, itemSerializationOptions);
                        bsonWriter.WriteEndDocument();
                    }
                    bsonWriter.WriteEndArray();
                    break;

                default:
                    var message = string.Format(
                        "'{0}' is not a valid {1} representation.",
                        representation,
                        BsonUtils.GetFriendlyTypeName(typeof(IDictionary <TKey, TValue>)));
                    throw new BsonSerializationException(message);
                }
            }
        }
Esempio n. 29
0
        /// <summary>
        /// Writes BSON binary data to the writer.
        /// </summary>
        /// <param name="bytes">The binary data.</param>
        /// <param name="subType">The binary data subtype.</param>
        /// <param name="guidRepresentation">The representation for Guids.</param>
        public override void WriteBinaryData(
            byte[] bytes,
            BsonBinarySubType subType,
            GuidRepresentation guidRepresentation)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException("JsonWriter");
            }
            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
            {
                ThrowInvalidState("WriteBinaryData", BsonWriterState.Value, BsonWriterState.Initial);
            }

            if (_jsonWriterSettings.OutputMode == JsonOutputMode.Shell)
            {
                WriteNameHelper(Name);
                switch (subType)
                {
                case BsonBinarySubType.UuidLegacy:
                case BsonBinarySubType.UuidStandard:
                    if (bytes.Length != 16)
                    {
                        var message = string.Format("Length of binary subtype {0} must be 16, not {1}.", subType, bytes.Length);
                        throw new ArgumentException(message);
                    }
                    if (subType == BsonBinarySubType.UuidLegacy && guidRepresentation == GuidRepresentation.Standard)
                    {
                        throw new ArgumentException("GuidRepresentation for binary subtype UuidLegacy must not be Standard.");
                    }
                    if (subType == BsonBinarySubType.UuidStandard && guidRepresentation != GuidRepresentation.Standard)
                    {
                        var message = string.Format("GuidRepresentation for binary subtype UuidStandard must be Standard, not {0}.", guidRepresentation);
                        throw new ArgumentException(message);
                    }
                    if (_jsonWriterSettings.ShellVersion >= new Version(2, 0, 0))
                    {
                        if (guidRepresentation == GuidRepresentation.Unspecified)
                        {
                            var s     = BsonUtils.ToHexString(bytes);
                            var parts = new string[]
                            {
                                s.Substring(0, 8),
                                s.Substring(8, 4),
                                s.Substring(12, 4),
                                s.Substring(16, 4),
                                s.Substring(20, 12)
                            };
                            _textWriter.Write("HexData({0}, \"{1}\")", (int)subType, string.Join("-", parts));
                        }
                        else
                        {
                            string uuidConstructorName;
                            switch (guidRepresentation)
                            {
                            case GuidRepresentation.CSharpLegacy: uuidConstructorName = "CSUUID"; break;

                            case GuidRepresentation.JavaLegacy: uuidConstructorName = "JUUID"; break;

                            case GuidRepresentation.PythonLegacy: uuidConstructorName = "PYUUID"; break;

                            case GuidRepresentation.Standard: uuidConstructorName = "UUID"; break;

                            default: throw new BsonInternalException("Unexpected GuidRepresentation");
                            }
                            var guid = GuidConverter.FromBytes(bytes, guidRepresentation);
                            _textWriter.Write("{0}(\"{1}\")", uuidConstructorName, guid.ToString());
                        }
                    }
                    else
                    {
                        _textWriter.Write("new BinData({0}, \"{1}\")", (int)subType, Convert.ToBase64String(bytes));
                    }
                    break;

                default:
                    _textWriter.Write("new BinData({0}, \"{1}\")", (int)subType, Convert.ToBase64String(bytes));
                    break;
                }
            }
            else
            {
                WriteStartDocument();
                WriteString("$binary", Convert.ToBase64String(bytes));
                WriteString("$type", ((int)subType).ToString("x2"));
                WriteEndDocument();
            }

            State = GetNextState();
        }
        public void ReadJson_should_return_expected_result_when_using_wrapped_bson_reader(string json, GuidRepresentation guidRepresentation, string nullableHexBytes, BsonBinarySubType subType)
        {
            var subject        = new BsonBinaryDataConverter();
            var expectedResult = nullableHexBytes == null ? null : new BsonBinaryData(BsonUtils.ParseHexString(nullableHexBytes), subType);

            var result = ReadJsonUsingWrappedBsonReader <BsonBinaryData>(subject, ToBson(json, guidRepresentation), mustBeNested: true, guidRepresentation: guidRepresentation);

            result.Should().Be(expectedResult);
        }