Represents serialization options for a KeyValuePair.
Inheritance: BsonBaseSerializationOptions
 /// <summary>
 /// Initializes a new instance of the DictionarySerializationOptions class.
 /// </summary>
 /// <param name="representation">The representation to use for a Dictionary.</param>
 /// <param name="keyValuePairSerializationOptions">The serialization options for the key/value pairs in the dictionary.</param>
 public DictionarySerializationOptions(DictionaryRepresentation representation, KeyValuePairSerializationOptions keyValuePairSerializationOptions)
 {
     if (keyValuePairSerializationOptions == null)
     {
         throw new ArgumentNullException("keyValuePairSerializationOptions");
     }
     _representation = representation;
     _keyValuePairSerializationOptions = keyValuePairSerializationOptions;
 }
Example #2
0
 /// <summary>
 /// Initializes a new instance of the DictionarySerializationOptions class.
 /// </summary>
 /// <param name="representation">The representation to use for a Dictionary.</param>
 /// <param name="keyValuePairSerializationOptions">The serialization options for the key/value pairs in the dictionary.</param>
 public DictionarySerializationOptions(DictionaryRepresentation representation, KeyValuePairSerializationOptions keyValuePairSerializationOptions)
 {
     if (keyValuePairSerializationOptions == null)
     {
         throw new ArgumentNullException("keyValuePairSerializationOptions");
     }
     _representation = representation;
     _keyValuePairSerializationOptions = keyValuePairSerializationOptions;
 }
 /// <summary>
 /// Initializes a new instance of the DictionarySerializationOptions class.
 /// </summary>
 /// <param name="representation">The representation to use for a Dictionary.</param>
 public DictionarySerializationOptions(DictionaryRepresentation representation)
 {
     _representation = representation;
     _keyValuePairSerializationOptions = (KeyValuePairSerializationOptions)KeyValuePairSerializationOptions.Defaults.Clone();
 }
 // constructors
 /// <summary>
 /// Initializes a new instance of the DictionarySerializationOptions class.
 /// </summary>
 public DictionarySerializationOptions()
 {
     _keyValuePairSerializationOptions = (KeyValuePairSerializationOptions)KeyValuePairSerializationOptions.Defaults.Clone();
 }
        // 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);
        }
        /// <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; // key might not be a string
                        if (name == null || (name.Length > 0 && 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);
                }
            }
        }
        //private KeyValuePair<string, string> DeserializeNameValue(BsonReader bsonReader)
        //{
        //    string key = null;
        //    string value = null;
        //    var bsonType = bsonReader.GetCurrentBsonType();
        //    if (bsonType == BsonType.Array)
        //    {
        //        // [["toto1", "tata1"], ["toto2", "tata2"]]

        //        bsonReader.ReadStartArray();
        //        //bsonReader.ReadBsonType();
        //        //var keyType = keyDiscriminatorConvention.GetActualType(bsonReader, typeof(TKey));
        //        //var keySerializer = GetKeySerializer(keyType);
        //        //key = (TKey)keySerializer.Deserialize(bsonReader, typeof(TKey), keyType, keyValuePairSerializationOptions.KeySerializationOptions);
        //        //bsonReader.ReadBsonType();
        //        //var valueType = valueDiscriminatorConvention.GetActualType(bsonReader, typeof(TValue));
        //        //var valueSerializer = GetValueSerializer(valueType);
        //        //value = (TValue)valueSerializer.Deserialize(bsonReader, typeof(TValue), valueType, keyValuePairSerializationOptions.ValueSerializationOptions);
        //        key = bsonReader.ReadString();
        //        value = bsonReader.ReadString();
        //        bsonReader.ReadEndArray();
        //    }
        //    else if (bsonType == BsonType.Document)
        //    {
        //        // [{ "k" : "toto1", "v" : "tata1" }, { "k" : "toto2", "v" : "tata2" }]

        //        bsonReader.ReadStartDocument();

        //        var bsonTrie = new BsonTrie<bool>();
        //        bsonTrie.Add("k", true); // is key
        //        bsonTrie.Add("v", false);

        //        bool keyFound = false, valueFound = false;
        //        bool elementFound;
        //        bool elementIsKey;
        //        while (bsonReader.ReadBsonType(bsonTrie, out elementFound, out elementIsKey) != BsonType.EndOfDocument)
        //        {
        //            var name = bsonReader.ReadName();
        //            if (elementFound)
        //            {
        //                if (elementIsKey)
        //                {
        //                    //var keyType = keyDiscriminatorConvention.GetActualType(bsonReader, typeof(TKey));
        //                    //var keySerializer = GetValueSerializer(keyType);
        //                    //key = (TKey)keySerializer.Deserialize(bsonReader, typeof(TKey), keyType, keyValuePairSerializationOptions.KeySerializationOptions);
        //                    key = bsonReader.ReadString();
        //                    keyFound = true;
        //                }
        //                else
        //                {
        //                    //var valueType = valueDiscriminatorConvention.GetActualType(bsonReader, typeof(TValue));
        //                    //var valueSerializer = GetValueSerializer(valueType);
        //                    //value = (TValue)valueSerializer.Deserialize(bsonReader, typeof(TValue), valueType, keyValuePairSerializationOptions.ValueSerializationOptions);
        //                    value = bsonReader.ReadString();
        //                    valueFound = true;
        //                }
        //            }
        //            else
        //            {
        //                var message = string.Format("Element '{0}' is not valid for KeyValuePairs (expecting 'k' or 'v').", name);
        //                throw new BsonSerializationException(message);
        //            }
        //        }
        //        bsonReader.ReadEndDocument();

        //        if (!keyFound)
        //        {
        //            //throw new FileFormatException("KeyValuePair item was missing the 'k' element.");
        //            throw new PBException("KeyValuePair item was missing the 'k' element.");
        //        }
        //        if (!valueFound)
        //        {
        //            //throw new FileFormatException("KeyValuePair item was missing the 'v' element.");
        //            throw new PBException("KeyValuePair item was missing the 'v' element.");
        //        }
        //    }
        //    else
        //    {
        //        //var message = string.Format("Cannot deserialize '{0}' from BsonType {1}.", BsonUtils.GetFriendlyTypeName(typeof(KeyValuePair<string, string>)), bsonType);
        //        //throw new FileFormatException(message);
        //        throw new PBException("Cannot deserialize '{0}' from BsonType {1}.", BsonUtils.GetFriendlyTypeName(typeof(KeyValuePair<string, string>)), bsonType);
        //    }
        //    return new KeyValuePair<string, string>(key, 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)
        {
            if (_trace)
                pb.Trace.WriteLine("NameValueCollectionSerializer.Serialize()");

            if (value == null)
            {
                bsonWriter.WriteNull();
            }
            else
            {
                // dont know why nominalType can be an object
                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;
                }

                // json Dictionary
                // { "toto1" : "tata1", "toto2" : "tata2" }

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

                if (dictionaryRepresentation == DictionaryRepresentation.Dynamic)
                {
                    // if some keys contain '$', '.' or '\0' serialize as ArrayOfArrays otherwise serialize as Document
                    dictionaryRepresentation = DictionaryRepresentation.Document;
                    foreach (string key in nameValueCollection.Keys)
                    {
                        //var name = key as string; // key might not be a string
                        if (string.IsNullOrEmpty(key) || key[0] == '$' || key.IndexOf('.') != -1 || key.IndexOf('\0') != -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);
                        //}
                        for (int i = 0; i < nameValueCollection.Count; i++)
                        {
                            bsonWriter.WriteString(nameValueCollection.GetKey(i), nameValueCollection.Get(i));
                        }
                        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)
                        for (int i = 0; i < nameValueCollection.Count; i++)
                        {
                            //var keyValuePair = new KeyValuePair<object, object>(dictionaryEntry.Key, dictionaryEntry.Value);
                            var keyValuePair = new KeyValuePair<string, string>(nameValueCollection.GetKey(i), nameValueCollection.Get(i));
                            //_keyValuePairSerializer.Serialize(bsonWriter, typeof(KeyValuePair<object, object>), keyValuePair, keyValuePairSerializationOptions);
                            _keyValuePairSerializer.Serialize(bsonWriter, typeof(KeyValuePair<string, string>), keyValuePair, keyValuePairSerializationOptions);
                        }
                        bsonWriter.WriteEndArray();

                        //bsonWriter.WriteStartArray();
                        //for (int i = 0; i < nameValueCollection.Count; i++)
                        //{
                        //    bsonWriter.WriteStartArray();
                        //    bsonWriter.WriteString(nameValueCollection.GetKey(i), nameValueCollection.Get(i));
                        //    bsonWriter.WriteEndArray();
                        //}
                        //bsonWriter.WriteEndArray();
                        break;
                    //case DictionaryRepresentation.ArrayOfDocuments:
                    //    bsonWriter.WriteStartArray();
                    //    for (int i = 0; i < nameValueCollection.Count; i++)
                    //    {
                    //        bsonWriter.WriteStartDocument();
                    //        bsonWriter.WriteString(nameValueCollection.GetKey(i), nameValueCollection.Get(i));
                    //        bsonWriter.WriteEndDocument();
                    //    }
                    //    bsonWriter.WriteEndArray();
                    //    break;
                    default:
                        var message = string.Format("'{0}' is not a valid IDictionary representation.", dictionaryRepresentation);
                        throw new BsonSerializationException(message);
                }
            }
        }
Example #8
0
 /// <summary>
 /// Initializes a new instance of the DictionarySerializationOptions class.
 /// </summary>
 /// <param name="representation">The representation to use for a Dictionary.</param>
 public DictionarySerializationOptions(DictionaryRepresentation representation)
 {
     _representation = representation;
     _keyValuePairSerializationOptions = (KeyValuePairSerializationOptions)KeyValuePairSerializationOptions.Defaults.Clone();
 }
Example #9
0
 // constructors
 /// <summary>
 /// Initializes a new instance of the DictionarySerializationOptions class.
 /// </summary>
 public DictionarySerializationOptions()
 {
     _keyValuePairSerializationOptions = (KeyValuePairSerializationOptions)KeyValuePairSerializationOptions.Defaults.Clone();
 }
Example #10
0
        // 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);
        }