public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
        {
            object value = null;
            if (bsonReader.CurrentBsonType == BsonType.Null)
            {
                bsonReader.ReadNull();
            }
            else
            {
                bsonReader.ReadStartArray();
                var idList = new List<ObjectId>();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var id = (ObjectId)BsonSerializer.Deserialize(bsonReader, typeof(ObjectId));
                    idList.Add(id);
                }
                bsonReader.ReadEndArray();

                if (idList.Count > 0)
                {
                    var cursor = MongoDbProvider.Database.GetCollection(DocumentType, DocumentType.Name)
                        .FindAs(DocumentType, Query.In("_id", BsonArray.Create(idList)));

                    var documents = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(DocumentType));
                    foreach (var document in cursor)
                    {
                        documents.Add(document);
                    }
                    value = documents;
                }
            }
            return value;
        }
        public override object Deserialize(
			BsonReader bsonReader,
			Type nominalType,
			IBsonSerializationOptions options
			)
        {
            var bsonType = bsonReader.GetCurrentBsonType();
            if (bsonType == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }

            var nvc = new NameValueCollection();

            bsonReader.ReadStartArray();
            while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
            {
                bsonReader.ReadStartArray();
                var key = (string)StringSerializer.Instance.Deserialize(bsonReader, typeof(string), options);
                var val = (string)StringSerializer.Instance.Deserialize(bsonReader, typeof(string), options);
                bsonReader.ReadEndArray();
                nvc.Add(key, val);
            }
            bsonReader.ReadEndArray();

            return nvc;
        }
        // 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(DateTimeOffset));

            BsonType bsonType = bsonReader.GetCurrentBsonType();
            long ticks;
            TimeSpan offset;
            switch (bsonType)
            {
                case BsonType.Array:
                    bsonReader.ReadStartArray();
                    ticks = bsonReader.ReadInt64();
                    offset = TimeSpan.FromMinutes(bsonReader.ReadInt32());
                    bsonReader.ReadEndArray();
                    return new DateTimeOffset(ticks, offset);
                case BsonType.Document:
                    bsonReader.ReadStartDocument();
                    bsonReader.ReadDateTime("DateTime"); // ignore value
                    ticks = bsonReader.ReadInt64("Ticks");
                    offset = TimeSpan.FromMinutes(bsonReader.ReadInt32("Offset"));
                    bsonReader.ReadEndDocument();
                    return new DateTimeOffset(ticks, offset);
                case BsonType.String:
                    return XmlConvert.ToDateTimeOffset(bsonReader.ReadString());
                default:
                    var message = string.Format("Cannot deserialize DateTimeOffset from BsonType {0}.", bsonType);
                    throw new Exception(message);
            }
        }
        public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
        {
            if (_trace)
                pb.Trace.WriteLine("ZStringArraySerializer.Deserialize()");

            VerifyTypes(nominalType, actualType, typeof(ZStringArray));

            var bsonType = bsonReader.GetCurrentBsonType();
            switch (bsonType)
            {
                case BsonType.Array:
                    bsonReader.ReadStartArray();
                    //return new ZString(bsonReader.ReadString());
                    var array = new List<string>();
                    bsonType = bsonReader.ReadBsonType();
                    while (bsonType != BsonType.EndOfDocument)
                    {
                        if (bsonType != BsonType.String)
                            throw new PBException("error ZStringArray cannot contain value of type {0}", bsonType);
                        var value = bsonReader.ReadString();
                        array.Add(value);
                        bsonType = bsonReader.ReadBsonType();
                    }
                    bsonReader.ReadEndArray();
                    return new ZStringArray(array.ToArray());
                default:
                    throw new PBException("error cannot deserialize ZStringArray from BsonType {0}.", bsonType);
            }
        }
 public override object Deserialize(
     BsonReader bsonReader,
     Type nominalType,
     IBsonSerializationOptions options
 )
 {
     var bsonType = bsonReader.CurrentBsonType;
     if (bsonType == BsonType.Null) {
         bsonReader.ReadNull();
         return null;
     } else if (bsonType == BsonType.Array) {
         bsonReader.ReadStartArray();
         var list = new ArrayList();
         var discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(typeof(object));
         while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) {
             var elementType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
             var serializer = BsonSerializer.LookupSerializer(elementType);
             var element = serializer.Deserialize(bsonReader, typeof(object), elementType, null);
             list.Add(element);
         }
         bsonReader.ReadEndArray();
         return list;
     } else {
         var message = string.Format("Can't deserialize a {0} from BsonType {1}", nominalType.FullName, bsonType);
         throw new FileFormatException(message);
     }
 }
        // 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(BsonArray));

            var bsonType = bsonReader.GetCurrentBsonType();
            switch (bsonType)
            {
                case BsonType.Array:
                    bsonReader.ReadStartArray();
                    var array = new BsonArray();
                    while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                    {
                        var value = (BsonValue)BsonValueSerializer.Instance.Deserialize(bsonReader, typeof(BsonValue), null);
                        array.Add(value);
                    }
                    bsonReader.ReadEndArray();
                    return array;
                default:
                    var message = string.Format("Cannot deserialize BsonArray from BsonType {0}.", bsonType);
                    throw new FileFormatException(message);
            }
        }
        // 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)
        {
            var arraySerializationOptions = EnsureSerializationOptions<ArraySerializationOptions>(options);
            var itemSerializationOptions = arraySerializationOptions.ItemSerializationOptions;

            var bsonType = bsonReader.GetCurrentBsonType();
            switch (bsonType)
            {
                case BsonType.Null:
                    bsonReader.ReadNull();
                    return null;

                case BsonType.Array:
                    var instance = CreateInstance(actualType);
                    var itemDiscriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object));
                    Type lastItemType = null;
                    IBsonSerializer lastItemSerializer = null;

                    bsonReader.ReadStartArray();
                    while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                    {
                        var itemType = itemDiscriminatorConvention.GetActualType(bsonReader, typeof(object));
                        IBsonSerializer itemSerializer;
                        if (itemType == lastItemType)
                        {
                            itemSerializer = lastItemSerializer;
                        }
                        else
                        {
                            itemSerializer = BsonSerializer.LookupSerializer(itemType);
                            lastItemType = itemType;
                            lastItemSerializer = itemSerializer;
                        }
                        var item = itemSerializer.Deserialize(bsonReader, typeof(object), itemType, itemSerializationOptions);
                        AddItem(instance, item);
                    }
                    bsonReader.ReadEndArray();

                    return FinalizeResult(instance, actualType);

                case BsonType.Document:
                    bsonReader.ReadStartDocument();
                    bsonReader.ReadString("_t"); // skip over discriminator
                    bsonReader.ReadName("_v");
                    var value = Deserialize(bsonReader, actualType, actualType, options);
                    bsonReader.ReadEndDocument();
                    return value;

                default:
                    var message = string.Format("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType);
                    throw new Exception(message);
            }
        }
 public void TestArrayEmpty() {
     var json = "[]";
     using (bsonReader = BsonReader.Create(json)) {
         Assert.AreEqual(BsonType.Array, bsonReader.ReadBsonType());
         bsonReader.ReadStartArray();
         Assert.AreEqual(BsonType.EndOfDocument, bsonReader.ReadBsonType());
         bsonReader.ReadEndArray();
         Assert.AreEqual(BsonReaderState.Done, bsonReader.State);
     }
     Assert.AreEqual(json, BsonSerializer.Deserialize<BsonArray>(new StringReader(json)).ToJson());
 }
Beispiel #9
0
        static IList ReadArray(BsonReader bsonReader)
        {
            var array = new ArrayList();

            bsonReader.ReadStartArray();
            while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                array.Add(ReadObject(bsonReader));
            bsonReader.ReadEndArray();

            return array;
        }
 public void TestArrayOneElement()
 {
     var json = "[1]";
     using (_bsonReader = new JsonReader(json))
     {
         Assert.AreEqual(BsonType.Array, _bsonReader.ReadBsonType());
         _bsonReader.ReadStartArray();
         Assert.AreEqual(BsonType.Int32, _bsonReader.ReadBsonType());
         Assert.AreEqual(1, _bsonReader.ReadInt32());
         Assert.AreEqual(BsonType.EndOfDocument, _bsonReader.ReadBsonType());
         _bsonReader.ReadEndArray();
         Assert.AreEqual(BsonReaderState.Done, _bsonReader.State);
     }
     Assert.AreEqual(json, BsonSerializer.Deserialize<BsonArray>(json).ToJson());
 }
        // 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)
        {
            if (bsonReader.GetCurrentBsonType() == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else
            {
                bsonReader.ReadStartArray();
                var x = (double)__doubleSerializer.Deserialize(bsonReader, typeof(double), null);
                var y = (double)__doubleSerializer.Deserialize(bsonReader, typeof(double), null);
                bsonReader.ReadEndArray();

                return new GeoJson2DCoordinates(x, y);
            }
        }
 public void TestArrayTwoElements()
 {
     var json = "[1, 2]";
     using (_bsonReader = BsonReader.Create(json))
     {
         Assert.AreEqual(BsonType.Array, _bsonReader.ReadBsonType());
         _bsonReader.ReadStartArray();
         Assert.AreEqual(BsonType.Int32, _bsonReader.ReadBsonType());
         Assert.AreEqual(1, _bsonReader.ReadInt32());
         Assert.AreEqual(BsonType.Int32, _bsonReader.ReadBsonType());
         Assert.AreEqual(2, _bsonReader.ReadInt32());
         Assert.AreEqual(BsonType.EndOfDocument, _bsonReader.ReadBsonType());
         _bsonReader.ReadEndArray();
         Assert.AreEqual(BsonReaderState.Done, _bsonReader.State);
     }
     Assert.AreEqual(json, BsonSerializer.Deserialize<BsonArray>(new StringReader(json)).ToJson());
 }
 /// <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="options">The serialization options.</param>
 /// <returns>An object.</returns>
 public override object Deserialize(
     BsonReader bsonReader,
     Type nominalType,
     IBsonSerializationOptions options
 ) {
     var bsonType = bsonReader.CurrentBsonType;
     if (bsonType == BsonType.Null) {
         bsonReader.ReadNull();
         return null;
     } else if (bsonType == BsonType.Document) {
         var dictionary = CreateInstance(nominalType);
         bsonReader.ReadStartDocument();
         var discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(typeof(object));
         while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) {
             var key = bsonReader.ReadName();
             var valueType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
             var valueSerializer = BsonSerializer.LookupSerializer(valueType);
             var value = valueSerializer.Deserialize(bsonReader, typeof(object), valueType, null);
             dictionary.Add(key, value);
         }
         bsonReader.ReadEndDocument();
         return dictionary;
     } else if (bsonType == BsonType.Array) {
         var dictionary = CreateInstance(nominalType);
         bsonReader.ReadStartArray();
         var discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(typeof(object));
         while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) {
             bsonReader.ReadStartArray();
             bsonReader.ReadBsonType();
             var keyType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
             var keySerializer = BsonSerializer.LookupSerializer(keyType);
             var key = keySerializer.Deserialize(bsonReader, typeof(object), keyType, null);
             bsonReader.ReadBsonType();
             var valueType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
             var valueSerializer = BsonSerializer.LookupSerializer(valueType);
             var value = valueSerializer.Deserialize(bsonReader, typeof(object), valueType, null);
             bsonReader.ReadEndArray();
             dictionary.Add(key, value);
         }
         bsonReader.ReadEndArray();
         return dictionary;
     } else {
         var message = string.Format("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType);
         throw new FileFormatException(message);
     }
 }
        // 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)
        {
            if (bsonReader.GetCurrentBsonType() == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else
            {
                bsonReader.ReadStartArray();
                var longitude = bsonReader.ReadDouble();
                var latitude = bsonReader.ReadDouble();
                bsonReader.ReadEndArray();

                return new GeoJson2DGeographicCoordinates(longitude, latitude);
            }
        }
        // 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)
        {
            if (bsonReader.GetCurrentBsonType() == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else
            {
                bsonReader.ReadStartArray();
                var easting = bsonReader.ReadDouble();
                var northing = bsonReader.ReadDouble();
                bsonReader.ReadEndArray();

                return new GeoJson2DProjectedCoordinates(easting, northing);
            }
        }
        // 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)
        {
            var arraySerializationOptions = EnsureSerializationOptions<ArraySerializationOptions>(options);
            var itemSerializationOptions = arraySerializationOptions.ItemSerializationOptions;

            var bsonType = bsonReader.GetCurrentBsonType();
            switch (bsonType)
            {
                case BsonType.Null:
                    bsonReader.ReadNull();
                    return null;
                case BsonType.Array:
                    bsonReader.ReadStartArray();
                    var queue = new Queue();
                    var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object));
                    while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                    {
                        var elementType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
                        var serializer = BsonSerializer.LookupSerializer(elementType);
                        var element = serializer.Deserialize(bsonReader, typeof(object), elementType, itemSerializationOptions);
                        queue.Enqueue(element);
                    }
                    bsonReader.ReadEndArray();
                    return queue;
                case BsonType.Document:
                    bsonReader.ReadStartDocument();
                    bsonReader.ReadString("_t"); // skip over discriminator
                    bsonReader.ReadName("_v");
                    var value = Deserialize(bsonReader, actualType, actualType, options);
                    bsonReader.ReadEndDocument();
                    return value;
                default:
                    var message = string.Format("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType);
                    throw new FileFormatException(message);
            }
        }
 public void TestNestedArray() {
     var json = "{ \"a\" : [1, 2] }";
     using (bsonReader = BsonReader.Create(json)) {
         Assert.AreEqual(BsonType.Document, bsonReader.ReadBsonType());
         bsonReader.ReadStartDocument();
         Assert.AreEqual(BsonType.Array, bsonReader.ReadBsonType());
         Assert.AreEqual("a", bsonReader.ReadName());
         bsonReader.ReadStartArray();
         Assert.AreEqual(1, bsonReader.ReadInt32());
         Assert.AreEqual(2, bsonReader.ReadInt32());
         bsonReader.ReadEndArray();
         bsonReader.ReadEndDocument();
         Assert.AreEqual(BsonReaderState.Done, bsonReader.State);
     }
     Assert.AreEqual(json, BsonSerializer.Deserialize<BsonDocument>(new StringReader(json)).ToJson());
 }
        // 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)
        {
            var dictionarySerializationOptions = EnsureSerializationOptions(options);
            var dictionaryRepresentation = dictionarySerializationOptions.Representation;
            var keyValuePairSerializationOptions = dictionarySerializationOptions.KeyValuePairSerializationOptions;

            var bsonType = bsonReader.GetCurrentBsonType();
            if (bsonType == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else if (bsonType == BsonType.Document)
            {
                if (nominalType == typeof(object))
                {
                    bsonReader.ReadStartDocument();
                    bsonReader.ReadString("_t"); // skip over discriminator
                    bsonReader.ReadName("_v");
                    var value = Deserialize(bsonReader, actualType, options); // recursive call replacing nominalType with actualType
                    bsonReader.ReadEndDocument();
                    return value;
                }

                var dictionary = CreateInstance(actualType);
                var valueDiscriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object));

                bsonReader.ReadStartDocument();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var key = bsonReader.ReadName();
                    var valueType = valueDiscriminatorConvention.GetActualType(bsonReader, typeof(object));
                    var valueSerializer = BsonSerializer.LookupSerializer(valueType);
                    var value = valueSerializer.Deserialize(bsonReader, typeof(object), valueType, keyValuePairSerializationOptions.ValueSerializationOptions);
                    dictionary.Add(key, value);
                }
                bsonReader.ReadEndDocument();

                return dictionary;
            }
            else if (bsonType == BsonType.Array)
            {
                var dictionary = CreateInstance(actualType);

                bsonReader.ReadStartArray();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var keyValuePair = (KeyValuePair<object, object>)_keyValuePairSerializer.Deserialize(
                        bsonReader,
                        typeof(KeyValuePair<object, object>),
                        keyValuePairSerializationOptions);
                    dictionary.Add(keyValuePair.Key, keyValuePair.Value);
                }
                bsonReader.ReadEndArray();

                return dictionary;
            }
            else
            {
                var message = string.Format("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType);
                throw new FileFormatException(message);
            }
        }
Beispiel #19
0
        //public static WebHeaderSerializer Instance { get { return __instance; } }

        public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
        {
            if (_trace)
                pb.Trace.WriteLine("WebHeaderSerializer.Deserialize()");

            var bsonType = bsonReader.GetCurrentBsonType();
            if (bsonType == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else if (bsonType == BsonType.Document)
            {
                if (nominalType == typeof(object))
                {
                    bsonReader.ReadStartDocument();
                    bsonReader.ReadString("_t"); // skip over discriminator
                    bsonReader.ReadName("_v");
                    var value = Deserialize(bsonReader, actualType, options); // recursive call replacing nominalType with actualType
                    bsonReader.ReadEndDocument();
                    return value;
                }

                var headers = new WebHeaderCollection();

                bsonReader.ReadStartDocument();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    string key = bsonReader.ReadName();

                    bsonType = bsonReader.GetCurrentBsonType();
                    if (bsonType == BsonType.String)
                    {
                        string value = bsonReader.ReadString();
                        headers.Add(key, value);
                    }
                    else if (bsonType == BsonType.Array)
                    {
                        bsonReader.ReadStartArray();
                        bsonType = bsonReader.ReadBsonType();
                        while (bsonType != BsonType.EndOfDocument)
                        {
                            if (bsonType != BsonType.String)
                                throw new PBException("invalid BsonType {0} for header array \"{1}\" value deserialize WebHeaderCollection.", bsonType, key);
                            string value = bsonReader.ReadString();
                            headers.Add(key, value);
                            bsonType = bsonReader.ReadBsonType();
                        }
                        bsonReader.ReadEndArray();
                    }
                    else
                        throw new PBException("error deserialize WebHeaderCollection, invalid BsonType {0} for \"{1}\".", bsonType, key);
                }
                bsonReader.ReadEndDocument();

                return headers;
            }
            else
            {
                throw new PBException("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType);
            }
        }
        // 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)
        {
            var dictionarySerializationOptions = EnsureSerializationOptions(options);
            var itemSerializationOptions = dictionarySerializationOptions.ItemSerializationOptions;

            var bsonType = bsonReader.GetCurrentBsonType();
            if (bsonType == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else if (bsonType == BsonType.Document)
            {
                if (nominalType == typeof(object))
                {
                    bsonReader.ReadStartDocument();
                    bsonReader.ReadString("_t"); // skip over discriminator
                    bsonReader.ReadName("_v");
                    var value = Deserialize(bsonReader, actualType, options); // recursive call replacing nominalType with actualType
                    bsonReader.ReadEndDocument();
                    return value;
                }

                var dictionary = CreateInstance(nominalType);
                bsonReader.ReadStartDocument();
                var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object));
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var key = bsonReader.ReadName();
                    var valueType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
                    var valueSerializer = BsonSerializer.LookupSerializer(valueType);
                    var value = valueSerializer.Deserialize(bsonReader, typeof(object), valueType, itemSerializationOptions);
                    dictionary.Add(key, value);
                }
                bsonReader.ReadEndDocument();
                return dictionary;
            }
            else if (bsonType == BsonType.Array)
            {
                var dictionary = CreateInstance(nominalType);
                bsonReader.ReadStartArray();
                var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object));
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var keyValuePairBsonType = bsonReader.GetCurrentBsonType();
                    if (keyValuePairBsonType == BsonType.Array)
                    {
                        bsonReader.ReadStartArray();
                        bsonReader.ReadBsonType();
                        var keyType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
                        var keySerializer = BsonSerializer.LookupSerializer(keyType);
                        var key = keySerializer.Deserialize(bsonReader, typeof(object), keyType, null); // no serialization options for key
                        bsonReader.ReadBsonType();
                        var valueType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
                        var valueSerializer = BsonSerializer.LookupSerializer(valueType);
                        var value = valueSerializer.Deserialize(bsonReader, typeof(object), valueType, itemSerializationOptions);
                        bsonReader.ReadEndArray();
                        dictionary.Add(key, value);
                    }
                    else if (keyValuePairBsonType == BsonType.Document)
                    {
                        bsonReader.ReadStartDocument();
                        object key = null;
                        object value = null;
                        bool keyFound = false, valueFound = false;
                        while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                        {
                            var name = bsonReader.ReadName();
                            switch (name)
                            {
                                case "k":
                                    var keyType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
                                    var keySerializer = BsonSerializer.LookupSerializer(keyType);
                                    key = keySerializer.Deserialize(bsonReader, typeof(object), keyType, null); // no serialization options for key
                                    keyFound = true;
                                    break;
                                case "v":
                                    var valueType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
                                    var valueSerializer = BsonSerializer.LookupSerializer(valueType);
                                    value = valueSerializer.Deserialize(bsonReader, typeof(object), valueType, itemSerializationOptions);
                                    valueFound = true;
                                    break;
                                default:
                                    var message = string.Format("Element '{0}' is not valid for Dictionary items (expecting 'k' or 'v').", name);
                                    throw new FileFormatException(message);
                            }
                        }
                        bsonReader.ReadEndDocument();
                        if (!keyFound)
                        {
                            throw new FileFormatException("Dictionary item was missing the 'k' element.");
                        }
                        if (!valueFound)
                        {
                            throw new FileFormatException("Dictionary item was missing the 'v' element.");
                        }
                        dictionary.Add(key, value);
                    }
                    else
                    {
                        var message = string.Format("Expected document or array for Dictionary item, not {0}.", keyValuePairBsonType);
                        throw new FileFormatException(message);
                    }
                }
                bsonReader.ReadEndArray();
                return dictionary;
            }
            else
            {
                var message = string.Format("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType);
                throw new FileFormatException(message);
            }
        }
        // public static properties
        /// <summary>
        /// Gets an instance of the DictionarySerializer class.
        /// </summary>
        //[Obsolete("Use constructor instead.")]
        //public static DictionarySerializer Instance
        //{
        //    get { return __instance; }
        //}

        // 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)
        {
            if (_trace)
                pb.Trace.WriteLine("NameValueCollectionSerializer.Deserialize()");

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

            var bsonType = bsonReader.GetCurrentBsonType();
            if (bsonType == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else if (bsonType == BsonType.Document)
            {
                // dont know why nominalType can be an object
                if (nominalType == typeof(object))
                {
                    bsonReader.ReadStartDocument();
                    bsonReader.ReadString("_t"); // skip over discriminator
                    bsonReader.ReadName("_v");
                    var value = Deserialize(bsonReader, actualType, options); // recursive call replacing nominalType with actualType
                    bsonReader.ReadEndDocument();
                    return value;
                }

                //var dictionary = CreateInstance(actualType);
                //var valueDiscriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object));

                // { "toto1" : "tata1", "toto2" : "tata2" }
                NameValueCollection nameValueCollection = new NameValueCollection();

                bsonReader.ReadStartDocument();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    //var key = bsonReader.ReadName();
                    //var valueType = valueDiscriminatorConvention.GetActualType(bsonReader, typeof(object));
                    //var valueSerializer = BsonSerializer.LookupSerializer(valueType);
                    //var value = valueSerializer.Deserialize(bsonReader, typeof(object), valueType, keyValuePairSerializationOptions.ValueSerializationOptions);
                    //dictionary.Add(key, value);
                    var key = bsonReader.ReadName();
                    var value = bsonReader.ReadString();
                    nameValueCollection.Add(key, value);
                }
                bsonReader.ReadEndDocument();

                return nameValueCollection;
            }
            else if (bsonType == BsonType.Array)
            {
                //var dictionary = CreateInstance(actualType);

                // DictionaryRepresentation.ArrayOfArrays
                // [["toto1", "tata1"], ["toto2", "tata2"]]
                // DictionaryRepresentation.ArrayOfDocuments
                // [{ "k" : "toto1", "v" : "tata1" }, { "k" : "toto2", "v" : "tata2" }]
                NameValueCollection nameValueCollection = new NameValueCollection();
                //KeyValuePairSerializer<string, string> keyValuePairSerializer = new KeyValuePairSerializer<string, string>();

                bsonReader.ReadStartArray();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    //var keyValuePair = (KeyValuePair<object, object>)_keyValuePairSerializer.Deserialize(
                    //    bsonReader,
                    //    typeof(KeyValuePair<object, object>),
                    //    keyValuePairSerializationOptions);
                    //dictionary.Add(keyValuePair.Key, keyValuePair.Value);
                    var keyValuePair = (KeyValuePair<string, string>)_keyValuePairSerializer.Deserialize(bsonReader, typeof(KeyValuePair<string, string>), keyValuePairSerializationOptions);
                    nameValueCollection.Add(keyValuePair.Key, keyValuePair.Value);
                }
                bsonReader.ReadEndArray();

                return nameValueCollection;
            }
            else
            {
                throw new PBException("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType);
            }
        }
        private static OXmlTabStop[] ReadTabs(BsonReader bsonReader)
        {
            bsonReader.ReadStartArray();
            List<OXmlTabStop> values = new List<OXmlTabStop>();
            while (true)
            {
                BsonType bsonType = bsonReader.ReadBsonType();
                if (bsonType == BsonType.EndOfDocument)
                    break;

                if (bsonType != BsonType.Document)
                    throw new PBException($"wrong Tabs value {bsonType}");
                bsonReader.ReadStartDocument();

                OXmlTabStop value = new OXmlTabStop();
                while (true)
                {
                    bsonType = bsonReader.ReadBsonType();
                    if (bsonType == BsonType.EndOfDocument)
                        break;
                    string name = bsonReader.ReadName();
                    switch (name.ToLower())
                    {
                        case "position":
                            if (bsonType == BsonType.Null)
                                break;
                            if (bsonType != BsonType.Int32)
                                throw new PBException($"wrong TabStop Position value {bsonType}");
                            value.Position = bsonReader.ReadInt32();
                            break;
                        case "alignment":
                            if (bsonType == BsonType.Null)
                                break;
                            if (bsonType != BsonType.String)
                                throw new PBException($"wrong TabStop Alignment value {bsonType}");
                            value.Alignment = bsonReader.ReadString().zParseEnum<TabStopValues>(ignoreCase: true);
                            break;
                        case "leaderchar":
                            if (bsonType == BsonType.Null)
                                break;
                            if (bsonType != BsonType.String)
                                throw new PBException($"wrong TabStop LeaderChar value {bsonType}");
                            value.LeaderChar = bsonReader.ReadString().zParseEnum<TabStopLeaderCharValues>(ignoreCase: true);
                            break;
                        default:
                            throw new PBException($"unknow TabStop value \"{name}\"");
                    }
                }
                bsonReader.ReadEndDocument();
                values.Add(value);
            }
            bsonReader.ReadEndArray();
            return values.ToArray();
        }