Example #1
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 (string.IsNullOrEmpty(name) || name[0] == '$' || name.IndexOf('.') != -1 || name.IndexOf('\0') != -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);
                }
            }
        }
        /// <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);
                }
            }
        }