// 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(CultureInfo));

            var bsonType = bsonReader.GetCurrentBsonType();
            switch (bsonType)
            {
                case BsonType.Null:
                    bsonReader.ReadNull();
                    return null;
                case BsonType.Document:
                    bsonReader.ReadStartDocument();
                    var name = bsonReader.ReadString("Name");
                    var useUserOverride = bsonReader.ReadBoolean("UseUserOverride");
                    bsonReader.ReadEndDocument();
                    return new CultureInfo(name, useUserOverride);
                case BsonType.String:
                    return new CultureInfo(bsonReader.ReadString());
                default:
                    var message = string.Format("Cannot deserialize CultureInfo 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)
        {
            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 FileFormatException(message);
            }
        }
        // public methods
#pragma warning disable 618 // about obsolete BsonBinarySubType.OldBinary
        /// <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(BitArray));

            BsonType bsonType = bsonReader.GetCurrentBsonType();
            BitArray bitArray;
            switch (bsonType)
            {
                case BsonType.Null:
                    bsonReader.ReadNull();
                    return null;
                case BsonType.Binary:
                    return new BitArray(bsonReader.ReadBytes());
                case BsonType.Document:
                    bsonReader.ReadStartDocument();
                    var length = bsonReader.ReadInt32("Length");
                    var bytes = bsonReader.ReadBytes("Bytes");
                    bsonReader.ReadEndDocument();
                    bitArray = new BitArray(bytes);
                    bitArray.Length = length;
                    return bitArray;
                case BsonType.String:
                    var s = bsonReader.ReadString();
                    bitArray = new BitArray(s.Length);
                    for (int i = 0; i < s.Length; i++)
                    {
                        var c = s[i];
                        switch (c)
                        {
                            case '0':
                                break;
                            case '1':
                                bitArray[i] = true;
                                break;
                            default:
                                throw new FileFormatException("String value is not a valid BitArray.");
                        }
                    }
                    return bitArray;
                default:
                    var message = string.Format("Cannot deserialize Byte[] 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="options">The serialization options.</param>
        /// <returns>An object.</returns>
        public object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
        {
            if (nominalType != typeof(object))
            {
                var message = string.Format("ObjectSerializer can only be used with nominal type System.Object, not type {0}.", nominalType.FullName);
                throw new InvalidOperationException(message);
            }

            var bsonType = bsonReader.GetCurrentBsonType();
            if (bsonType == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else if (bsonType == BsonType.Document)
            {
                var bookmark = bsonReader.GetBookmark();
                bsonReader.ReadStartDocument();
                if (bsonReader.ReadBsonType() == BsonType.EndOfDocument)
                {
                    bsonReader.ReadEndDocument();
                    return new object();
                }
                else
                {
                    bsonReader.ReturnToBookmark(bookmark);
                }
            }

            var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object));
            var actualType = discriminatorConvention.GetActualType(bsonReader, typeof(object));
            if (actualType == typeof(object))
            {
                var message = string.Format("Unable to determine actual type of object to deserialize. NominalType is System.Object and BsonType is {0}.", bsonType);
                throw new FileFormatException(message);
            }

            var serializer = BsonSerializer.LookupSerializer(actualType);
            return serializer.Deserialize(bsonReader, nominalType, actualType, options);
        }
        // public methods
        /// <summary>
        /// Deserializes an object of type System.Drawing.Size 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(System.Drawing.Size));

            var bsonType = bsonReader.GetCurrentBsonType();
            switch (bsonType)
            {
                case BsonType.Document:
                    bsonReader.ReadStartDocument();
                    var width = bsonReader.ReadInt32("Width");
                    var height = bsonReader.ReadInt32("Height");
                    bsonReader.ReadEndDocument();
                    return new System.Drawing.Size(width, height);
                default:
                    var message = string.Format("Cannot deserialize Size from BsonType {0}.", bsonType);
                    throw new FileFormatException(message);
            }
        }
        // private methods
        private bool IsCSharpNullRepresentation(BsonReader bsonReader)
        {
            var bookmark = bsonReader.GetBookmark();
            bsonReader.ReadStartDocument();
            var bsonType = bsonReader.ReadBsonType();
            if (bsonType == BsonType.Boolean)
            {
                var name = bsonReader.ReadName();
                if (name == "_csharpnull" || name == "$csharpnull")
                {
                    var value = bsonReader.ReadBoolean();
                    if (value)
                    {
                        bsonType = bsonReader.ReadBsonType();
                        if (bsonType == BsonType.EndOfDocument)
                        {
                            bsonReader.ReadEndDocument();
                            return true;
                        }
                    }
                }
            }

            bsonReader.ReturnToBookmark(bookmark);
            return false;
        }
Exemple #7
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)
        {
            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(TValue));

                bsonReader.ReadStartDocument();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var key             = (TKey)(object)bsonReader.ReadName();
                    var valueType       = valueDiscriminatorConvention.GetActualType(bsonReader, typeof(TValue));
                    var valueSerializer = BsonSerializer.LookupSerializer(valueType);
                    var value           = (TValue)valueSerializer.Deserialize(bsonReader, typeof(TValue), 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 <TKey, TValue>)_keyValuePairSerializer.Deserialize(
                        bsonReader,
                        typeof(KeyValuePair <TKey, TValue>),
                        keyValuePairSerializationOptions);
                    dictionary.Add(keyValuePair);
                }
                bsonReader.ReadEndArray();

                return(dictionary);
            }
            else
            {
                var message = string.Format("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType);
                throw new FileFormatException(message);
            }
        }
        /// <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 object Deserialize(
            BsonReader bsonReader,
            Type nominalType,
            Type actualType,
            IBsonSerializationOptions options)
        {
            VerifyNominalType(nominalType);
            var bsonType = bsonReader.GetCurrentBsonType();
            if (bsonType == Bson.BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else
            {
                if (actualType != _classMap.ClassType)
                {
                    var message = string.Format("BsonClassMapSerializer.Deserialize for type {0} was called with actualType {1}.",
                        BsonUtils.GetFriendlyTypeName(_classMap.ClassType), BsonUtils.GetFriendlyTypeName(actualType));
                    throw new BsonSerializationException(message);
                }

                if (actualType.IsValueType)
                {
                    var message = string.Format("Value class {0} cannot be deserialized.", actualType.FullName);
                    throw new BsonSerializationException(message);
                }

                if (_classMap.IsAnonymous)
                {
                    throw new InvalidOperationException("An anonymous class cannot be deserialized.");
                }

                if (bsonType != BsonType.Document)
                {
                    var message = string.Format(
                        "Expected a nested document representing the serialized form of a {0} value, but found a value of type {1} instead.",
                        actualType.FullName, bsonType);
                    throw new FileFormatException(message);
                }

                Dictionary<string, object> values = null;
                object obj = null;
                ISupportInitialize supportsInitialization = null;
                if (_classMap.HasCreatorMaps)
                {
                    // for creator-based deserialization we first gather the values in a dictionary and then call a matching creator
                    values = new Dictionary<string, object>();
                }
                else
                {
                    // for mutable classes we deserialize the values directly into the result object
                    obj = _classMap.CreateInstance();

                    supportsInitialization = obj as ISupportInitialize;
                    if (supportsInitialization != null)
                    {
                        supportsInitialization.BeginInit();
                    }
                }

                var discriminatorConvention = _classMap.GetDiscriminatorConvention();
                var allMemberMaps = _classMap.AllMemberMaps;
                var extraElementsMemberMapIndex = _classMap.ExtraElementsMemberMapIndex;
                var memberMapBitArray = FastMemberMapHelper.GetBitArray(allMemberMaps.Count);

                bsonReader.ReadStartDocument();
                var elementTrie = _classMap.ElementTrie;
                bool memberMapFound;
                int memberMapIndex;
                while (bsonReader.ReadBsonType(elementTrie, out memberMapFound, out memberMapIndex) != BsonType.EndOfDocument)
                {
                    var elementName = bsonReader.ReadName();
                    if (memberMapFound)
                    {
                        var memberMap = allMemberMaps[memberMapIndex];
                        if (memberMapIndex != extraElementsMemberMapIndex)
                        {
                            if (obj != null)
                            {
                                if (memberMap.IsReadOnly)
                                {
                                    bsonReader.SkipValue();
                                }
                                else
                                {
                                    var value = DeserializeMemberValue(bsonReader, memberMap);
                                    memberMap.Setter(obj, value);
                                }
                            }
                            else
                            {
                                var value = DeserializeMemberValue(bsonReader, memberMap);
                                values[elementName] = value;
                            }
                        }
                        else
                        {
                            DeserializeExtraElement(bsonReader, obj, elementName, memberMap);
                        }
                        memberMapBitArray[memberMapIndex >> 5] |= 1U << (memberMapIndex & 31);
                    }
                    else
                    {
                        if (elementName == discriminatorConvention.ElementName)
                        {
                            bsonReader.SkipValue(); // skip over discriminator
                            continue;
                        }

                        if (extraElementsMemberMapIndex >= 0)
                        {
                            DeserializeExtraElement(bsonReader, obj, elementName, _classMap.ExtraElementsMemberMap);
                            memberMapBitArray[extraElementsMemberMapIndex >> 5] |= 1U << (extraElementsMemberMapIndex & 31);
                        }
                        else if (_classMap.IgnoreExtraElements)
                        {
                            bsonReader.SkipValue();
                        }
                        else
                        {
                            //james.wei 针对/_id属性没有扩展映射的提示。
                            var message = string.Format("Element '{0}' does not match any field or property of class {1}.",elementName, _classMap.ClassType.FullName);
                            throw new FileFormatException(message);
                        }
                    }
                }
                bsonReader.ReadEndDocument();

                // check any members left over that we didn't have elements for (in blocks of 32 elements at a time)
                for (var bitArrayIndex = 0; bitArrayIndex < memberMapBitArray.Length; ++bitArrayIndex)
                {
                    memberMapIndex = bitArrayIndex << 5;
                    var memberMapBlock = ~memberMapBitArray[bitArrayIndex]; // notice that bits are flipped so 1's are now the missing elements

                    // work through this memberMapBlock of 32 elements
                    while (true)
                    {
                        // examine missing elements (memberMapBlock is shifted right as we work through the block)
                        for (; (memberMapBlock & 1) != 0; ++memberMapIndex, memberMapBlock >>= 1)
                        {
                            var memberMap = allMemberMaps[memberMapIndex];
                            if (memberMap.IsReadOnly)
                            {
                                continue;
                            }

                            if (memberMap.IsRequired)
                            {
                                var fieldOrProperty = (memberMap.MemberInfo.MemberType == MemberTypes.Field) ? "field" : "property";
                                var message = string.Format(
                                    "Required element '{0}' for {1} '{2}' of class {3} is missing.",
                                    memberMap.ElementName, fieldOrProperty, memberMap.MemberName, _classMap.ClassType.FullName);
                                throw new FileFormatException(message);
                            }

                            if (obj != null)
                            {
                                memberMap.ApplyDefaultValue(obj);
                            }
                            else if (memberMap.IsDefaultValueSpecified && !memberMap.IsReadOnly)
                            {
                                values[memberMap.ElementName] = memberMap.DefaultValue;
                            }
                        }

                        if (memberMapBlock == 0)
                        {
                            break;
                        }

                        // skip ahead to the next missing element
                        var leastSignificantBit = FastMemberMapHelper.GetLeastSignificantBit(memberMapBlock);
                        memberMapIndex += leastSignificantBit;
                        memberMapBlock >>= leastSignificantBit;
                    }
                }

                if (obj != null)
                {
                    if (supportsInitialization != null)
                    {
                        supportsInitialization.EndInit();
                    }

                    return obj;
                }
                else
                {
                    return CreateInstanceUsingCreator(values);
                }

            }
        }
        public void TestBookmark()
        {
            var json = "{ \"x\" : 1, \"y\" : 2 }";

            using (_bsonReader = BsonReader.Create(json))
            {
                // do everything twice returning to bookmark in between
                var bookmark = _bsonReader.GetBookmark();
                Assert.AreEqual(BsonType.Document, _bsonReader.ReadBsonType());
                _bsonReader.ReturnToBookmark(bookmark);
                Assert.AreEqual(BsonType.Document, _bsonReader.ReadBsonType());

                bookmark = _bsonReader.GetBookmark();
                _bsonReader.ReadStartDocument();
                _bsonReader.ReturnToBookmark(bookmark);
                _bsonReader.ReadStartDocument();

                bookmark = _bsonReader.GetBookmark();
                Assert.AreEqual(BsonType.Int32, _bsonReader.ReadBsonType());
                _bsonReader.ReturnToBookmark(bookmark);
                Assert.AreEqual(BsonType.Int32, _bsonReader.ReadBsonType());

                bookmark = _bsonReader.GetBookmark();
                Assert.AreEqual("x", _bsonReader.ReadName());
                _bsonReader.ReturnToBookmark(bookmark);
                Assert.AreEqual("x", _bsonReader.ReadName());

                bookmark = _bsonReader.GetBookmark();
                Assert.AreEqual(1, _bsonReader.ReadInt32());
                _bsonReader.ReturnToBookmark(bookmark);
                Assert.AreEqual(1, _bsonReader.ReadInt32());

                bookmark = _bsonReader.GetBookmark();
                Assert.AreEqual(BsonType.Int32, _bsonReader.ReadBsonType());
                _bsonReader.ReturnToBookmark(bookmark);
                Assert.AreEqual(BsonType.Int32, _bsonReader.ReadBsonType());

                bookmark = _bsonReader.GetBookmark();
                Assert.AreEqual("y", _bsonReader.ReadName());
                _bsonReader.ReturnToBookmark(bookmark);
                Assert.AreEqual("y", _bsonReader.ReadName());

                bookmark = _bsonReader.GetBookmark();
                Assert.AreEqual(2, _bsonReader.ReadInt32());
                _bsonReader.ReturnToBookmark(bookmark);
                Assert.AreEqual(2, _bsonReader.ReadInt32());

                bookmark = _bsonReader.GetBookmark();
                Assert.AreEqual(BsonType.EndOfDocument, _bsonReader.ReadBsonType());
                _bsonReader.ReturnToBookmark(bookmark);
                Assert.AreEqual(BsonType.EndOfDocument, _bsonReader.ReadBsonType());

                bookmark = _bsonReader.GetBookmark();
                _bsonReader.ReadEndDocument();
                _bsonReader.ReturnToBookmark(bookmark);
                _bsonReader.ReadEndDocument();

                Assert.AreEqual(BsonReaderState.Done, _bsonReader.State);
            }
            Assert.AreEqual(json, BsonSerializer.Deserialize <BsonDocument>(new StringReader(json)).ToJson());
        }
        // explicit interface implementation
        object IBsonSerializable.Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
        {
            if (bsonReader.CurrentBsonType == Bson.BsonType.Null)
            {
                bsonReader.ReadNull();
                return(null);
            }
            else
            {
                bsonReader.ReadStartDocument();
                BsonType bsonType;
                while ((bsonType = bsonReader.ReadBsonType()) != BsonType.EndOfDocument)
                {
                    var name = bsonReader.ReadName();
                    switch (name)
                    {
                    case "abbreviated":
                        abbreviated = bsonReader.ReadString();
                        break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    case "ns":
                        @namespace = bsonReader.ReadString();
                        break;

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

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

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

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

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

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

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

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

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

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

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

                    default:
                        break;     // ignore unknown elements
                    }
                }
                bsonReader.ReadEndDocument();
                return(this);
            }
        }
        // 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(BsonNull));

            var bsonType = bsonReader.GetCurrentBsonType();
            string message;
            switch (bsonType)
            {
                case BsonType.Null:
                    bsonReader.ReadNull();
                    return BsonNull.Value;
                case BsonType.Document:
                    bsonReader.ReadStartDocument();
                    var name = bsonReader.ReadName();
                    if (name == "_csharpnull" || name == "$csharpnull")
                    {
                        var csharpNull = bsonReader.ReadBoolean();
                        bsonReader.ReadEndDocument();
                        return csharpNull ? null : BsonNull.Value;
                    }
                    else
                    {
                        message = string.Format("Unexpected element name while deserializing a BsonNull: {0}.", name);
                        throw new FileFormatException(message);
                    }
                default:
                    message = string.Format("Cannot deserialize BsonNull from BsonType {0}.", bsonType);
                    throw new FileFormatException(message);
            }
        }
Exemple #12
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);
            }
        }
Exemple #13
0
        // public methods
#pragma warning disable 618 // about obsolete BsonBinarySubType.OldBinary
        /// <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(BitArray));

            BsonType bsonType = bsonReader.GetCurrentBsonType();
            BitArray bitArray;

            byte[]            bytes;
            BsonBinarySubType subType;
            string            message;

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

            case BsonType.Binary:
                bsonReader.ReadBinaryData(out bytes, out subType);
                if (subType != BsonBinarySubType.Binary && subType != BsonBinarySubType.OldBinary)
                {
                    message = string.Format("Invalid Binary sub type {0}.", subType);
                    throw new FileFormatException(message);
                }
                return(new BitArray(bytes));

            case BsonType.Document:
                bsonReader.ReadStartDocument();
                var length = bsonReader.ReadInt32("Length");
                bsonReader.ReadBinaryData("Bytes", out bytes, out subType);
                if (subType != BsonBinarySubType.Binary && subType != BsonBinarySubType.OldBinary)
                {
                    message = string.Format("Invalid Binary sub type {0}.", subType);
                    throw new FileFormatException(message);
                }
                bsonReader.ReadEndDocument();
                bitArray        = new BitArray(bytes);
                bitArray.Length = length;
                return(bitArray);

            case BsonType.String:
                var s = bsonReader.ReadString();
                bitArray = new BitArray(s.Length);
                for (int i = 0; i < s.Length; i++)
                {
                    var c = s[i];
                    switch (c)
                    {
                    case '0':
                        break;

                    case '1':
                        bitArray[i] = true;
                        break;

                    default:
                        throw new FileFormatException("String value is not a valid BitArray.");
                    }
                }
                return(bitArray);

            default:
                message = string.Format("Cannot deserialize Byte[] from BsonType {0}.", bsonType);
                throw new FileFormatException(message);
            }
        }
        private static OXmlPageMargin ReadPageMargin(BsonReader bsonReader)
        {
            bsonReader.ReadStartDocument();
            OXmlPageMargin value = new OXmlPageMargin();

            while (true)
            {
                BsonType bsonType = bsonReader.ReadBsonType();
                if (bsonType == BsonType.EndOfDocument)
                {
                    break;
                }
                string name = bsonReader.ReadName();
                switch (name.ToLower())
                {
                case "top":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.Int32)
                    {
                        throw new PBException($"wrong PageMargin Top value {bsonType}");
                    }
                    value.Top = bsonReader.ReadInt32();
                    break;

                case "bottom":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.Int32)
                    {
                        throw new PBException($"wrong PageMargin Bottom value {bsonType}");
                    }
                    value.Bottom = bsonReader.ReadInt32();
                    break;

                case "left":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.Int32)
                    {
                        throw new PBException($"wrong PageMargin Left value {bsonType}");
                    }
                    value.Left = bsonReader.ReadInt32();
                    break;

                case "right":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.Int32)
                    {
                        throw new PBException($"wrong PageMargin Right value {bsonType}");
                    }
                    value.Right = bsonReader.ReadInt32();
                    break;

                case "header":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.Int32)
                    {
                        throw new PBException($"wrong PageMargin Header value {bsonType}");
                    }
                    value.Header = bsonReader.ReadInt32();
                    break;

                case "footer":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.Int32)
                    {
                        throw new PBException($"wrong PageMargin Footer value {bsonType}");
                    }
                    value.Footer = bsonReader.ReadInt32();
                    break;

                default:
                    throw new PBException($"unknow PageMargin value \"{name}\"");
                }
            }
            bsonReader.ReadEndDocument();
            return(value);
        }
        // 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 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(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 = new BsonDateTime(bsonReader.ReadDateTime()).ToUniversalTime();
                    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 methods
        /// <summary>
        /// Deserializes an Bitmap from a BsonReader.
        /// </summary>
        /// <param name="bsonReader">The BsonReader.</param>
        /// <param name="nominalType">The nominal type of the Bitmap.</param>
        /// <param name="actualType">The actual type of the Bitmap.</param>
        /// <param name="options">The serialization options.</param>
        /// <returns>A Bitmap.</returns>
        public override object Deserialize(
            BsonReader bsonReader,
            Type nominalType,
            Type actualType,
            IBsonSerializationOptions options)
        {
            if (nominalType != typeof(Image) && nominalType != typeof(Bitmap))
            {
                var message = string.Format("Nominal type must be Image or Bitmap, not {0}.", nominalType.FullName);
                throw new ArgumentException(message, "nominalType");
            }

            if (actualType != typeof(Bitmap))
            {
                var message = string.Format("Actual type must be Bitmap, not {0}.", actualType.FullName);
                throw new ArgumentException(message, "actualType");
            }

            var bsonType = bsonReader.GetCurrentBsonType();
            byte[] bytes;
            BsonBinarySubType subType;
            switch (bsonType)
            {
                case BsonType.Null:
                    bsonReader.ReadNull();
                    return null;

                case BsonType.Binary:
                    bsonReader.ReadBinaryData(out bytes, out subType);
                    break;

                case BsonType.Document:
                    bsonReader.ReadStartDocument();
                    bsonReader.ReadString("_t");
                    bsonReader.ReadBinaryData("bitmap", out bytes, out subType);
                    bsonReader.ReadEndDocument();
                    break;

                default:
                    var message = string.Format("BsonType must be Null, Binary or Document, not {0}.", bsonType);
                    throw new FileFormatException(message);
            }

            if (subType != BsonBinarySubType.Binary)
            {
                var message = string.Format("Binary sub type must be Binary, not {0}.", subType);
                throw new FileFormatException(message);
            }

            var stream = new MemoryStream(bytes);
            return new Bitmap(stream);
        }
Exemple #18
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);
            }
        }
        /// <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(T[, ]));

            var    bsonType = bsonReader.CurrentBsonType;
            string message;

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

            case BsonType.Array:
                bsonReader.ReadStartArray();
                var outerList = new List <List <T> >();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    bsonReader.ReadStartArray();
                    var innerList = new List <T>();
                    while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                    {
                        var element = BsonSerializer.Deserialize <T>(bsonReader);
                        innerList.Add(element);
                    }
                    bsonReader.ReadEndArray();
                    outerList.Add(innerList);
                }
                bsonReader.ReadEndArray();

                var length1 = outerList.Count;
                var length2 = (length1 == 0) ? 0 : outerList[0].Count;
                var array   = new T[length1, length2];
                for (int i = 0; i < length1; i++)
                {
                    var innerList = outerList[i];
                    if (innerList.Count != length2)
                    {
                        message = string.Format("Inner list {0} is of length {1} but should be of length {2}.", i, innerList.Count, length2);
                        throw new FileFormatException(message);
                    }
                    for (int j = 0; j < length2; j++)
                    {
                        array[i, j] = innerList[j];
                    }
                }

                return(array);

            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:
                message = string.Format("Can't deserialize a {0} from BsonType {1}.", actualType.FullName, bsonType);
                throw new FileFormatException(message);
            }
        }
 public object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
 {
     this.VerifyNominalType(nominalType);
     if (bsonReader.CurrentBsonType == BsonType.Null)
     {
         bsonReader.ReadNull();
         return((object)null);
     }
     else
     {
         if (actualType.IsValueType)
         {
             throw new BsonSerializationException(string.Format("Value class {0} cannot be deserialized.", (object)actualType.FullName));
         }
         BsonClassMap bsonClassMap = BsonClassMap.LookupClassMap(actualType);
         if (bsonClassMap.IsAnonymous)
         {
             throw new InvalidOperationException("An anonymous class cannot be deserialized.");
         }
         // Added
         object instance = CreateInstance(bsonClassMap);
         // Added
         if (bsonReader.CurrentBsonType != BsonType.Document)
         {
             throw new FileFormatException(string.Format("Expected a nested document representing the serialized form of a {0} value, but found a value of type {1} instead.", (object)actualType.FullName, (object)bsonReader.CurrentBsonType));
         }
         bsonReader.ReadStartDocument();
         HashSet <BsonMemberMap>  hashSet = new HashSet <BsonMemberMap>(bsonClassMap.MemberMaps);
         IDiscriminatorConvention discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(nominalType);
         while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
         {
             string elementName = bsonReader.ReadName();
             if (elementName == discriminatorConvention.ElementName)
             {
                 bsonReader.SkipValue();
             }
             else
             {
                 BsonMemberMap memberMapForElement = bsonClassMap.GetMemberMapForElement(elementName);
                 if (memberMapForElement != null && memberMapForElement != bsonClassMap.ExtraElementsMemberMap)
                 {
                     this.DeserializeMember(bsonReader, instance, memberMapForElement);
                     hashSet.Remove(memberMapForElement);
                 }
                 else if (bsonClassMap.ExtraElementsMemberMap != null)
                 {
                     this.DeserializeExtraElement(bsonReader, instance, elementName, bsonClassMap.ExtraElementsMemberMap);
                 }
                 else
                 {
                     if (!bsonClassMap.IgnoreExtraElements)
                     {
                         throw new FileFormatException(string.Format("Element '{0}' does not match any field or property of class {1}.", (object)elementName, (object)bsonClassMap.ClassType.FullName));
                     }
                     bsonReader.SkipValue();
                 }
             }
         }
         bsonReader.ReadEndDocument();
         foreach (BsonMemberMap bsonMemberMap in hashSet)
         {
             if (bsonMemberMap.IsRequired)
             {
                 string str = bsonMemberMap.MemberInfo.MemberType == MemberTypes.Field ? "field" : "property";
                 throw new FileFormatException(string.Format("Required element '{0}' for {1} '{2}' of class {3} is missing.", (object)bsonMemberMap.ElementName, (object)str, (object)bsonMemberMap.MemberName, (object)bsonClassMap.ClassType.FullName));
             }
             else if (bsonMemberMap.HasDefaultValue)
             {
                 bsonMemberMap.ApplyDefaultValue(instance);
             }
         }
         return(instance);
     }
 }
Exemple #21
0
        /// <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 object Deserialize(
            BsonReader bsonReader,
            Type nominalType,
            Type actualType,
            IBsonSerializationOptions options
            )
        {
            VerifyNominalType(nominalType);
            if (bsonReader.CurrentBsonType == Bson.BsonType.Null)
            {
                bsonReader.ReadNull();
                return(null);
            }
            else
            {
                if (actualType.IsValueType)
                {
                    var message = string.Format("Value class cannot be deserialized: '{0}'", actualType.FullName);
                    throw new BsonSerializationException(message);
                }

                var classMap = BsonClassMap.LookupClassMap(actualType);
                if (classMap.IsAnonymous)
                {
                    throw new InvalidOperationException("Anonymous class cannot be deserialized");
                }
                var obj = classMap.CreateInstance();

                bsonReader.ReadStartDocument();
                var missingElementMemberMaps = new HashSet <BsonMemberMap>(classMap.MemberMaps); // make a copy!
                var discriminatorConvention  = BsonDefaultSerializer.LookupDiscriminatorConvention(nominalType);
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var elementName = bsonReader.ReadName();
                    if (elementName == discriminatorConvention.ElementName)
                    {
                        bsonReader.SkipValue(); // skip over discriminator
                        continue;
                    }

                    var memberMap = classMap.GetMemberMapForElement(elementName);
                    if (memberMap != null && memberMap != classMap.ExtraElementsMemberMap)
                    {
                        DeserializeMember(bsonReader, obj, memberMap);
                        missingElementMemberMaps.Remove(memberMap);
                    }
                    else
                    {
                        if (classMap.ExtraElementsMemberMap != null)
                        {
                            DeserializeExtraElement(bsonReader, obj, elementName, classMap.ExtraElementsMemberMap);
                        }
                        else if (classMap.IgnoreExtraElements)
                        {
                            bsonReader.SkipValue();
                        }
                        else
                        {
                            string message = string.Format("Unexpected element: {0}", elementName);
                            throw new FileFormatException(message);
                        }
                    }
                }
                bsonReader.ReadEndDocument();

                foreach (var memberMap in missingElementMemberMaps)
                {
                    if (memberMap.IsRequired)
                    {
                        var message = string.Format("Required element is missing: {0}", memberMap.ElementName);
                        throw new FileFormatException(message);
                    }

                    if (memberMap.HasDefaultValue)
                    {
                        memberMap.ApplyDefaultValue(obj);
                    }
                }

                return(obj);
            }
        }
        // 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(Version));

            BsonType bsonType = bsonReader.GetCurrentBsonType();
            string   message;

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

            case BsonType.Document:
                bsonReader.ReadStartDocument();
                int major = -1, minor = -1, build = -1, revision = -1;
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var name = bsonReader.ReadName();
                    switch (name)
                    {
                    case "Major": major = bsonReader.ReadInt32(); break;

                    case "Minor": minor = bsonReader.ReadInt32(); break;

                    case "Build": build = bsonReader.ReadInt32(); break;

                    case "Revision": revision = bsonReader.ReadInt32(); break;

                    default:
                        message = string.Format("Unrecognized element '{0}' while deserializing a Version value.", name);
                        throw new Exception(message);
                    }
                }
                bsonReader.ReadEndDocument();
                if (major == -1)
                {
                    message = string.Format("Version missing Major element.");
                    throw new Exception(message);
                }
                else if (minor == -1)
                {
                    message = string.Format("Version missing Minor element.");
                    throw new Exception(message);
                }
                else if (build == -1)
                {
                    return(new Version(major, minor));
                }
                else if (revision == -1)
                {
                    return(new Version(major, minor, build));
                }
                else
                {
                    return(new Version(major, minor, build, revision));
                }

            case BsonType.String:
                return(new Version(bsonReader.ReadString()));

            default:
                message = string.Format("Cannot deserialize Version from BsonType {0}.", bsonType);
                throw new Exception(message);
            }
        }
Exemple #23
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(KeyValuePair <TKey, TValue>));
            var keyValuePairSerializationOptions = EnsureSerializationOptions <KeyValuePairSerializationOptions>(options);

            var    keyDiscriminatorConvention   = GetKeyDiscriminatorConvention();
            var    valueDiscriminatorConvention = GetValueDiscriminatorConvention();
            TKey   key;
            TValue value;

            var bsonType = bsonReader.GetCurrentBsonType();

            if (bsonType == BsonType.Array)
            {
                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);
                bsonReader.ReadEndArray();
            }
            else if (bsonType == BsonType.Document)
            {
                bsonReader.ReadStartDocument();
                key   = default(TKey);
                value = default(TValue);
                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);
                            keyFound = true;
                        }
                        else
                        {
                            var valueType       = valueDiscriminatorConvention.GetActualType(bsonReader, typeof(TValue));
                            var valueSerializer = GetValueSerializer(valueType);
                            value      = (TValue)valueSerializer.Deserialize(bsonReader, typeof(TValue), valueType, keyValuePairSerializationOptions.ValueSerializationOptions);
                            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.");
                }
                if (!valueFound)
                {
                    throw new FileFormatException("KeyValuePair item was missing the 'v' element.");
                }
            }
            else
            {
                var message = string.Format(
                    "Cannot deserialize '{0}' from BsonType {1}.",
                    BsonUtils.GetFriendlyTypeName(typeof(KeyValuePair <TKey, TValue>)),
                    bsonType);
                throw new FileFormatException(message);
            }

            return(new KeyValuePair <TKey, TValue>(key, value));
        }
        /// <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 object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
        {
            VerifyNominalType(nominalType);
            if (bsonReader.CurrentBsonType == Bson.BsonType.Null)
            {
                bsonReader.ReadNull();
                return(null);
            }
            else
            {
                if (actualType.IsValueType)
                {
                    var message = string.Format("Value class {0} cannot be deserialized.", actualType.FullName);
                    throw new BsonSerializationException(message);
                }

                var classMap = BsonClassMap.LookupClassMap(actualType);
                if (classMap.IsAnonymous)
                {
                    throw new InvalidOperationException("An anonymous class cannot be deserialized.");
                }
                var obj = classMap.CreateInstance();

                if (bsonReader.CurrentBsonType != BsonType.Document)
                {
                    var message = string.Format(
                        "Expected a nested document representing the serialized form of a {0} value, but found a value of type {1} instead.",
                        actualType.FullName, bsonReader.CurrentBsonType);
                    throw new FileFormatException(message);
                }

                bsonReader.ReadStartDocument();
                var missingElementMemberMaps = new HashSet <BsonMemberMap>(classMap.MemberMaps); // make a copy!
                var discriminatorConvention  = BsonDefaultSerializer.LookupDiscriminatorConvention(nominalType);
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var elementName = bsonReader.ReadName();
                    if (elementName == discriminatorConvention.ElementName)
                    {
                        bsonReader.SkipValue(); // skip over discriminator
                        continue;
                    }

                    var memberMap = classMap.GetMemberMapForElement(elementName);
                    if (memberMap != null && memberMap != classMap.ExtraElementsMemberMap)
                    {
                        DeserializeMember(bsonReader, obj, memberMap);
                        missingElementMemberMaps.Remove(memberMap);
                    }
                    else
                    {
                        if (classMap.ExtraElementsMemberMap != null)
                        {
                            DeserializeExtraElement(bsonReader, obj, elementName, classMap.ExtraElementsMemberMap);
                        }
                        else if (classMap.IgnoreExtraElements)
                        {
                            bsonReader.SkipValue();
                        }
                        else
                        {
                            var message = string.Format(
                                "Element '{0}' does not match any field or property of class {1}.",
                                elementName, classMap.ClassType.FullName);
                            throw new FileFormatException(message);
                        }
                    }
                }
                bsonReader.ReadEndDocument();

                foreach (var memberMap in missingElementMemberMaps)
                {
                    if (memberMap.IsRequired)
                    {
                        var fieldOrProperty = (memberMap.MemberInfo.MemberType == MemberTypes.Field) ? "field" : "property";
                        var message         = string.Format(
                            "Required element '{0}' for {1} '{2}' of class {3} is missing.",
                            memberMap.ElementName, fieldOrProperty, memberMap.MemberName, classMap.ClassType.FullName);
                        throw new FileFormatException(message);
                    }

                    if (memberMap.HasDefaultValue)
                    {
                        memberMap.ApplyDefaultValue(obj);
                    }
                }

                return(obj);
            }
        }
        // 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 = new BsonDateTime(bsonReader.ReadDateTime()).ToUniversalTime();
                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);
        }
Exemple #26
0
        /// <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 object Deserialize(
            BsonReader bsonReader,
            Type nominalType,
            Type actualType,
            IBsonSerializationOptions options)
        {
            VerifyNominalType(nominalType);
            var bsonType = bsonReader.GetCurrentBsonType();

            if (bsonType == Bson.BsonType.Null)
            {
                bsonReader.ReadNull();
                return(null);
            }
            else
            {
                if (actualType != _classMap.ClassType)
                {
                    var message = string.Format("BsonClassMapSerializer.Deserialize for type {0} was called with actualType {1}.",
                                                BsonUtils.GetFriendlyTypeName(_classMap.ClassType), BsonUtils.GetFriendlyTypeName(actualType));
                    throw new BsonSerializationException(message);
                }

                if (actualType.IsValueType)
                {
                    var message = string.Format("Value class {0} cannot be deserialized.", actualType.FullName);
                    throw new BsonSerializationException(message);
                }

                if (_classMap.IsAnonymous)
                {
                    throw new InvalidOperationException("An anonymous class cannot be deserialized.");
                }
                var obj = _classMap.CreateInstance();

                if (bsonType != BsonType.Document)
                {
                    var message = string.Format(
                        "Expected a nested document representing the serialized form of a {0} value, but found a value of type {1} instead.",
                        actualType.FullName, bsonType);
                    throw new FileFormatException(message);
                }

                var supportsInitialization = obj as ISupportInitialize;
                if (supportsInitialization != null)
                {
                    supportsInitialization.BeginInit();
                }

                var discriminatorConvention = _classMap.GetDiscriminatorConvention();
                var fastMemberMapFinder     = new FastMemberMapFinder(_classMap);

                bsonReader.ReadStartDocument();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var elementName = bsonReader.ReadName();
                    if (elementName == discriminatorConvention.ElementName)
                    {
                        bsonReader.SkipValue(); // skip over discriminator
                        continue;
                    }

                    var memberMap = fastMemberMapFinder.GetMemberMapForElement(elementName);
                    if (memberMap != null)
                    {
                        if (memberMap.IsReadOnly)
                        {
                            bsonReader.SkipValue();
                        }
                        else
                        {
                            DeserializeMember(bsonReader, obj, memberMap);
                        }
                    }
                    else
                    {
                        if (_classMap.ExtraElementsMemberMap != null)
                        {
                            DeserializeExtraElement(bsonReader, obj, elementName, _classMap.ExtraElementsMemberMap);
                        }
                        else if (_classMap.IgnoreExtraElements)
                        {
                            bsonReader.SkipValue();
                        }
                        else
                        {
                            var message = string.Format(
                                "Element '{0}' does not match any field or property of class {1}.",
                                elementName, _classMap.ClassType.FullName);
                            throw new FileFormatException(message);
                        }
                    }
                }
                bsonReader.ReadEndDocument();

                // check any members left over that we didn't have elements for
                if (fastMemberMapFinder.HasLeftOverMemberMaps())
                {
                    foreach (var memberMap in fastMemberMapFinder.GetLeftOverMemberMaps())
                    {
                        if (memberMap.IsReadOnly)
                        {
                            continue;
                        }

                        if (memberMap.IsRequired)
                        {
                            var fieldOrProperty = (memberMap.MemberInfo.MemberType == MemberTypes.Field) ? "field" : "property";
                            var message         = string.Format(
                                "Required element '{0}' for {1} '{2}' of class {3} is missing.",
                                memberMap.ElementName, fieldOrProperty, memberMap.MemberName, _classMap.ClassType.FullName);
                            throw new FileFormatException(message);
                        }

                        memberMap.ApplyDefaultValue(obj);
                    }
                }

                if (supportsInitialization != null)
                {
                    supportsInitialization.EndInit();
                }

                return(obj);
            }
        }
        // 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(BsonDateTime));
            var dateTimeSerializationOptions = EnsureSerializationOptions<DateTimeSerializationOptions>(options);

            var bsonType = bsonReader.GetCurrentBsonType();
            if (bsonType == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else
            {
                long? millisecondsSinceEpoch = null;
                long? ticks = null;
                switch (bsonType)
                {
                    case BsonType.DateTime:
                        millisecondsSinceEpoch = bsonReader.ReadDateTime();
                        break;
                    case BsonType.Document:
                        bsonReader.ReadStartDocument();
                        millisecondsSinceEpoch = bsonReader.ReadDateTime("DateTime");
                        bsonReader.ReadName("Ticks");
                        var ticksValue = BsonValue.ReadFrom(bsonReader);
                        if (!ticksValue.IsBsonUndefined)
                        {
                            ticks = ticksValue.ToInt64();
                        }
                        bsonReader.ReadEndDocument();
                        break;
                    case BsonType.Int64:
                        ticks = bsonReader.ReadInt64();
                        break;
                    case BsonType.String:
                        // note: we're not using XmlConvert because of bugs in Mono
                        DateTime dateTime;
                        if (dateTimeSerializationOptions.DateOnly)
                        {
                            dateTime = 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", };
                            dateTime = DateTime.ParseExact(bsonReader.ReadString(), formats, null, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
                        }
                        ticks = dateTime.Ticks;
                        break;
                    default:
                        var message = string.Format("Cannot deserialize DateTime from BsonType {0}.", bsonType);
                        throw new FileFormatException(message);
                }

                BsonDateTime bsonDateTime;
                if (ticks.HasValue)
                {
                    bsonDateTime = BsonDateTime.Create(new DateTime(ticks.Value, DateTimeKind.Utc));
                }
                else
                {
                    bsonDateTime = BsonDateTime.Create(millisecondsSinceEpoch.Value);
                }

                if (dateTimeSerializationOptions.DateOnly)
                {
                    var dateTime = bsonDateTime.Value;
                    if (dateTime.TimeOfDay != TimeSpan.Zero)
                    {
                        throw new FileFormatException("TimeOfDay component for DateOnly DateTime value is not zero.");
                    }
                    bsonDateTime = BsonDateTime.Create(DateTime.SpecifyKind(dateTime, dateTimeSerializationOptions.Kind)); // not ToLocalTime or ToUniversalTime!
                }
                else
                {
                    if (bsonDateTime.IsValidDateTime)
                    {
                        var dateTime = bsonDateTime.Value;
                        switch (dateTimeSerializationOptions.Kind)
                        {
                            case DateTimeKind.Local:
                            case DateTimeKind.Unspecified:
                                dateTime = DateTime.SpecifyKind(BsonUtils.ToLocalTime(dateTime), dateTimeSerializationOptions.Kind);
                                break;
                            case DateTimeKind.Utc:
                                dateTime = BsonUtils.ToUniversalTime(dateTime);
                                break;
                        }
                        bsonDateTime = BsonDateTime.Create(dateTime);
                    }
                    else
                    {
                        if (dateTimeSerializationOptions.Kind != DateTimeKind.Utc)
                        {
                            throw new FileFormatException("BsonDateTime is outside the range of .NET DateTime.");
                        }
                    }
                }

                return bsonDateTime;
            }
        }
Exemple #28
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(T[, ]));
            var arraySerializationOptions = EnsureSerializationOptions <ArraySerializationOptions>(options);
            var itemSerializationOptions  = arraySerializationOptions.ItemSerializationOptions;

            var    bsonType = bsonReader.GetCurrentBsonType();
            string message;

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

            case BsonType.Array:
                var             itemNominalType             = typeof(T);
                var             itemNominalTypeIsValueType  = itemNominalType.IsValueType;
                var             itemNominalTypeSerializer   = BsonSerializer.LookupSerializer(itemNominalType);
                var             itemDiscriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(itemNominalType);
                Type            lastItemType       = null;
                IBsonSerializer lastItemSerializer = null;

                // if itemNominalType is a value type then these assignments are final
                var itemActualType           = itemNominalType;
                var itemActualTypeSerializer = itemNominalTypeSerializer;

                bsonReader.ReadStartArray();
                var outerList = new List <List <T> >();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    bsonReader.ReadStartArray();
                    var innerList = new List <T>();
                    while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                    {
                        if (!itemNominalTypeIsValueType)
                        {
                            itemActualType = itemDiscriminatorConvention.GetActualType(bsonReader, itemNominalType);
                            if (itemActualType == itemNominalType)
                            {
                                itemActualTypeSerializer = itemNominalTypeSerializer;
                            }
                            else if (itemActualType == lastItemType)
                            {
                                itemActualTypeSerializer = lastItemSerializer;
                            }
                            else
                            {
                                itemActualTypeSerializer = BsonSerializer.LookupSerializer(itemActualType);
                                lastItemType             = itemActualType;
                                lastItemSerializer       = itemActualTypeSerializer;
                            }
                        }
                        var item = (T)itemActualTypeSerializer.Deserialize(bsonReader, itemNominalType, itemActualType, itemSerializationOptions);
                        innerList.Add(item);
                    }
                    bsonReader.ReadEndArray();
                    outerList.Add(innerList);
                }
                bsonReader.ReadEndArray();

                var length1 = outerList.Count;
                var length2 = (length1 == 0) ? 0 : outerList[0].Count;
                var array   = new T[length1, length2];
                for (int i = 0; i < length1; i++)
                {
                    var innerList = outerList[i];
                    if (innerList.Count != length2)
                    {
                        message = string.Format("Inner list {0} is of length {1} but should be of length {2}.", i, innerList.Count, length2);
                        throw new FileFormatException(message);
                    }
                    for (int j = 0; j < length2; j++)
                    {
                        array[i, j] = innerList[j];
                    }
                }

                return(array);

            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:
                message = string.Format("Can't deserialize a {0} from BsonType {1}.", actualType.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(BsonDocument));

            var bsonType = bsonReader.GetCurrentBsonType();
            string message;
            switch (bsonType)
            {
                case BsonType.Document:
                    var documentSerializationOptions = (options ?? DocumentSerializationOptions.Defaults) as DocumentSerializationOptions;
                    if (documentSerializationOptions == null)
                    {
                        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);
                    }

                    bsonReader.ReadStartDocument();
                    var document = new BsonDocument(documentSerializationOptions.AllowDuplicateNames);
                    while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                    {
                        var name = bsonReader.ReadName();
                        var value = (BsonValue)BsonValueSerializer.Instance.Deserialize(bsonReader, typeof(BsonValue), null);
                        document.Add(name, value);
                    }
                    bsonReader.ReadEndDocument();

                    return document;
                default:
                    message = string.Format("Cannot deserialize BsonDocument from BsonType {0}.", bsonType);
                    throw new FileFormatException(message);
            }
        }
        /// <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 bsonType = bsonReader.CurrentBsonType;

            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 = 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)
                {
                    if (bsonReader.CurrentBsonType == 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);
                        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);
                    }
                    else if (bsonReader.CurrentBsonType == 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);
                                keyFound = true;
                                break;

                            case "v":
                                var valueType       = discriminatorConvention.GetActualType(bsonReader, typeof(object));
                                var valueSerializer = BsonSerializer.LookupSerializer(valueType);
                                value      = valueSerializer.Deserialize(bsonReader, typeof(object), valueType, null);
                                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}.", bsonReader.CurrentBsonType);
                        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);
            }
        }
        // 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(T[, , ]));
            var arraySerializationOptions = EnsureSerializationOptions <ArraySerializationOptions>(options);
            var itemSerializationOptions  = arraySerializationOptions.ItemSerializationOptions;

            var    bsonType = bsonReader.GetCurrentBsonType();
            string message;

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

            case BsonType.Array:
                bsonReader.ReadStartArray();
                var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(T));
                var outerList = new List <List <List <T> > >();
                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    bsonReader.ReadStartArray();
                    var middleList = new List <List <T> >();
                    while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                    {
                        bsonReader.ReadStartArray();
                        var innerList = new List <T>();
                        while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                        {
                            var elementType = discriminatorConvention.GetActualType(bsonReader, typeof(T));
                            var serializer  = BsonSerializer.LookupSerializer(elementType);
                            var element     = (T)serializer.Deserialize(bsonReader, typeof(T), elementType, itemSerializationOptions);
                            innerList.Add(element);
                        }
                        bsonReader.ReadEndArray();
                        middleList.Add(innerList);
                    }
                    bsonReader.ReadEndArray();
                    outerList.Add(middleList);
                }
                bsonReader.ReadEndArray();

                var length1 = outerList.Count;
                var length2 = (length1 == 0) ? 0 : outerList[0].Count;
                var length3 = (length2 == 0) ? 0 : outerList[0][0].Count;
                var array   = new T[length1, length2, length3];
                for (int i = 0; i < length1; i++)
                {
                    var middleList = outerList[i];
                    if (middleList.Count != length2)
                    {
                        message = string.Format("Middle list {0} is of length {1} but should be of length {2}.", i, middleList.Count, length2);
                        throw new FileFormatException(message);
                    }
                    for (int j = 0; j < length2; j++)
                    {
                        var innerList = middleList[j];
                        if (innerList.Count != length3)
                        {
                            message = string.Format("Inner list {0} is of length {1} but should be of length {2}.", j, innerList.Count, length3);
                            throw new FileFormatException(message);
                        }
                        for (int k = 0; k < length3; k++)
                        {
                            array[i, j, k] = innerList[k];
                        }
                    }
                }

                return(array);

            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:
                message = string.Format("Can't deserialize a {0} from BsonType {1}.", actualType.FullName, bsonType);
                throw new FileFormatException(message);
            }
        }
        /// <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 object Deserialize(
            BsonReader bsonReader,
            Type nominalType,
            Type actualType,
            IBsonSerializationOptions options)
        {
            VerifyNominalType(nominalType);
            var bsonType = bsonReader.GetCurrentBsonType();

            if (bsonType == Bson.BsonType.Null)
            {
                bsonReader.ReadNull();
                return(null);
            }
            else
            {
                if (actualType != _classMap.ClassType)
                {
                    var message = string.Format("BsonClassMapSerializer.Deserialize for type {0} was called with actualType {1}.",
                                                BsonUtils.GetFriendlyTypeName(_classMap.ClassType), BsonUtils.GetFriendlyTypeName(actualType));
                    throw new BsonSerializationException(message);
                }

                if (actualType.IsValueType)
                {
                    var message = string.Format("Value class {0} cannot be deserialized.", actualType.FullName);
                    throw new BsonSerializationException(message);
                }

                if (_classMap.IsAnonymous)
                {
                    throw new InvalidOperationException("An anonymous class cannot be deserialized.");
                }
                var obj = _classMap.CreateInstance();

                if (bsonType != BsonType.Document)
                {
                    var message = string.Format(
                        "Expected a nested document representing the serialized form of a {0} value, but found a value of type {1} instead.",
                        actualType.FullName, bsonType);
                    throw new FileFormatException(message);
                }

                var supportsInitialization = obj as ISupportInitialize;
                if (supportsInitialization != null)
                {
                    supportsInitialization.BeginInit();
                }

                var discriminatorConvention     = _classMap.GetDiscriminatorConvention();
                var allMemberMaps               = _classMap.AllMemberMaps;
                var extraElementsMemberMapIndex = _classMap.ExtraElementsMemberMapIndex;
                var memberMapBitArray           = FastMemberMapHelper.GetBitArray(allMemberMaps.Count);

                bsonReader.ReadStartDocument();
                var  elementTrie = _classMap.ElementTrie;
                bool memberMapFound;
                int  memberMapIndex;
                while (bsonReader.ReadBsonType(elementTrie, out memberMapFound, out memberMapIndex) != BsonType.EndOfDocument)
                {
                    var elementName = bsonReader.ReadName();
                    if (memberMapFound)
                    {
                        var memberMap = allMemberMaps[memberMapIndex];
                        if (memberMapIndex != extraElementsMemberMapIndex)
                        {
                            if (memberMap.IsReadOnly)
                            {
                                bsonReader.SkipValue();
                            }
                            else
                            {
                                DeserializeMember(bsonReader, obj, memberMap);
                            }
                        }
                        else
                        {
                            DeserializeExtraElement(bsonReader, obj, elementName, memberMap);
                        }
                        memberMapBitArray[memberMapIndex >> 5] |= 1U << (memberMapIndex & 31);
                    }
                    else
                    {
                        if (elementName == discriminatorConvention.ElementName)
                        {
                            bsonReader.SkipValue(); // skip over discriminator
                            continue;
                        }

                        if (extraElementsMemberMapIndex >= 0)
                        {
                            DeserializeExtraElement(bsonReader, obj, elementName, _classMap.ExtraElementsMemberMap);
                            memberMapBitArray[extraElementsMemberMapIndex >> 5] |= 1U << (extraElementsMemberMapIndex & 31);
                        }
                        else if (_classMap.IgnoreExtraElements)
                        {
                            bsonReader.SkipValue();
                        }
                        else
                        {
                            var message = string.Format(
                                "Element '{0}' does not match any field or property of class {1}.",
                                elementName, _classMap.ClassType.FullName);
                            throw new FileFormatException(message);
                        }
                    }
                }
                bsonReader.ReadEndDocument();

                // check any members left over that we didn't have elements for (in blocks of 32 elements at a time)
                for (var bitArrayIndex = 0; bitArrayIndex < memberMapBitArray.Length; ++bitArrayIndex)
                {
                    memberMapIndex = bitArrayIndex << 5;
                    var memberMapBlock = ~memberMapBitArray[bitArrayIndex]; // notice that bits are flipped so 1's are now the missing elements

                    // work through this memberMapBlock of 32 elements
                    for (;;)
                    {
                        // examine missing elements (memberMapBlock is shifted right as we work through the block)
                        for (; (memberMapBlock & 1) != 0; ++memberMapIndex, memberMapBlock >>= 1)
                        {
                            var memberMap = allMemberMaps[memberMapIndex];
                            if (memberMap.IsReadOnly)
                            {
                                continue;
                            }

                            if (memberMap.IsRequired)
                            {
                                var fieldOrProperty = (memberMap.MemberInfo.MemberType == MemberTypes.Field) ? "field" : "property";
                                var message         = string.Format(
                                    "Required element '{0}' for {1} '{2}' of class {3} is missing.",
                                    memberMap.ElementName, fieldOrProperty, memberMap.MemberName, _classMap.ClassType.FullName);
                                throw new FileFormatException(message);
                            }
                            memberMap.ApplyDefaultValue(obj);
                        }

                        if (memberMapBlock == 0)
                        {
                            break;
                        }

                        // skip ahead to the next missing element
                        var leastSignificantBit = FastMemberMapHelper.GetLeastSignificantBit(memberMapBlock);
                        memberMapIndex  += leastSignificantBit;
                        memberMapBlock >>= leastSignificantBit;
                    }
                }

                if (supportsInitialization != null)
                {
                    supportsInitialization.EndInit();
                }

                return(obj);
            }
        }
        // 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);
            }
        }
        // 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(Version));

            BsonType bsonType = bsonReader.GetCurrentBsonType();
            string message;
            switch (bsonType)
            {
                case BsonType.Null:
                    bsonReader.ReadNull();
                    return null;
                case BsonType.Document:
                    bsonReader.ReadStartDocument();
                    int major = -1, minor = -1, build = -1, revision = -1;
                    while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                    {
                        var name = bsonReader.ReadName();
                        switch (name)
                        {
                            case "Major": major = bsonReader.ReadInt32(); break;
                            case "Minor": minor = bsonReader.ReadInt32(); break;
                            case "Build": build = bsonReader.ReadInt32(); break;
                            case "Revision": revision = bsonReader.ReadInt32(); break;
                            default:
                                message = string.Format("Unrecognized element '{0}' while deserializing a Version value.", name);
                                throw new FileFormatException(message);
                        }
                    }
                    bsonReader.ReadEndDocument();
                    if (major == -1)
                    {
                        message = string.Format("Version missing Major element.");
                        throw new FileFormatException(message);
                    }
                    else if (minor == -1)
                    {
                        message = string.Format("Version missing Minor element.");
                        throw new FileFormatException(message);
                    }
                    else if (build == -1)
                    {
                        return new Version(major, minor);
                    }
                    else if (revision == -1)
                    {
                        return new Version(major, minor, build);
                    }
                    else
                    {
                        return new Version(major, minor, build, revision);
                    }
                case BsonType.String:
                    return new Version(bsonReader.ReadString());
                default:
                    message = string.Format("Cannot deserialize Version from BsonType {0}.", bsonType);
                    throw new FileFormatException(message);
            }
        }
        /// <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 object Deserialize(
           BsonReader bsonReader,
           Type nominalType,
           Type actualType,
           IBsonSerializationOptions options)
        {
            if (actualType != typeof(object))
            {
                var message = string.Format("ObjectSerializer can only be used with actual type System.Object, not type {0}.", actualType.FullName);
                throw new ArgumentException(message, "actualType");
            }

            var bsonType = bsonReader.GetCurrentBsonType();
            if (bsonType == BsonType.Null)
            {
                bsonReader.ReadNull();
                return null;
            }
            else if (bsonType == BsonType.Document)
            {
                bsonReader.ReadStartDocument();
                if (bsonReader.ReadBsonType() == BsonType.EndOfDocument)
                {
                    bsonReader.ReadEndDocument();
                    return new object();
                }
                else
                {
                    var message = string.Format("A document being deserialized to System.Object must be empty.");
                    throw new FileFormatException(message);
                }
            }
            else
            {
                var message = string.Format("Cannot deserialize System.Object from BsonType {0}.", bsonType);
                throw new FileFormatException(message);
            }
        }
Exemple #37
0
        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          os = new ObjectSerializer();
                MongoDynamic md = new MongoDynamic();
                bsonReader.ReadStartDocument();

                Dictionary <string, Type> typeMap = null;

                // scan document first to find interfaces
                {
                    var bookMark = bsonReader.GetBookmark();
                    if (bsonReader.FindElement(MongoDynamic.InterfacesField))
                    {
                        md[MongoDynamic.InterfacesField] = BsonSerializer.Deserialize <BsonValue>(bsonReader).AsBsonArray.Select(x => x.AsString);
                        typeMap = md.GetTypeMap();
                    }
                    else
                    {
                        throw new FormatException("No interfaces defined for this dynamic object - can't deserialize it");
                    }
                    bsonReader.ReturnToBookmark(bookMark);
                }

                while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    var name = bsonReader.ReadName();

                    if (name == "_id")
                    {
                        //md[name] = BsonValue.ReadFrom(bsonReader).AsObjectId;
                        md[name] = BsonSerializer.Deserialize <ObjectId>(bsonReader);
                    }
                    else if (name == MongoDynamic.InterfacesField)
                    {
                        // Read it and ignore it, we already have it
                        //BsonValue.ReadFrom(bsonReader);
                        BsonSerializer.Deserialize <ObjectId>(bsonReader);
                    }
                    else
                    {
                        if (typeMap == null)
                        {
                            throw new FormatException("No interfaces define for this dynamic object - can't deserialize");
                        }
                        // lookup the type for this element according to the interfaces
                        Type elementType;
                        if (typeMap.TryGetValue(name, out elementType))
                        {
                            var value = BsonSerializer.Deserialize(bsonReader, elementType);
                            md[name] = value;
                        }
                        else
                        {
                            // This is a value that is no longer in the interface, maybe a column you removed
                            // not really much we can do with it ... but we need to read it and move on
                            var value = BsonSerializer.Deserialize(bsonReader, typeof(object));
                            md[name] = value;

                            // As with all databases, removing elements from the schema is always going to cause problems ...
                        }
                    }
                }
                bsonReader.ReadEndDocument();
                return(md);
            }
            else
            {
                var message = string.Format("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType);
                throw new FormatException(message);
            }
        }
Exemple #38
0
        public static OXmlRunFonts ReadRunFonts(BsonReader bsonReader)
        {
            bsonReader.ReadStartDocument();
            OXmlRunFonts value = new OXmlRunFonts();

            while (true)
            {
                BsonType bsonType = bsonReader.ReadBsonType();
                if (bsonType == BsonType.EndOfDocument)
                {
                    break;
                }
                string name = bsonReader.ReadName();
                switch (name.ToLower())
                {
                case "ascii":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.String)
                    {
                        throw new PBException($"wrong RunFonts Ascii value {bsonType}");
                    }
                    value.Ascii = bsonReader.ReadString();
                    break;

                case "asciitheme":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.String)
                    {
                        throw new PBException($"wrong RunFonts AsciiTheme value {bsonType}");
                    }
                    value.AsciiTheme = bsonReader.ReadString().zParseEnum <ThemeFontValues>(ignoreCase: true);
                    break;

                case "complexscript":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.String)
                    {
                        throw new PBException($"wrong RunFonts ComplexScript value {bsonType}");
                    }
                    value.ComplexScript = bsonReader.ReadString();
                    break;

                case "complexscripttheme":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.String)
                    {
                        throw new PBException($"wrong RunFonts ComplexScriptTheme value {bsonType}");
                    }
                    value.ComplexScriptTheme = bsonReader.ReadString().zParseEnum <ThemeFontValues>(ignoreCase: true);
                    break;

                case "eastasia":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.String)
                    {
                        throw new PBException($"wrong RunFonts EastAsia value {bsonType}");
                    }
                    value.EastAsia = bsonReader.ReadString();
                    break;

                case "eastasiatheme":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.String)
                    {
                        throw new PBException($"wrong RunFonts EastAsiaTheme value {bsonType}");
                    }
                    value.EastAsiaTheme = bsonReader.ReadString().zParseEnum <ThemeFontValues>(ignoreCase: true);
                    break;

                case "highansi":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.String)
                    {
                        throw new PBException($"wrong RunFonts HighAnsi value {bsonType}");
                    }
                    value.HighAnsi = bsonReader.ReadString();
                    break;

                case "highansitheme":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.String)
                    {
                        throw new PBException($"wrong RunFonts HighAnsiTheme value {bsonType}");
                    }
                    value.HighAnsiTheme = bsonReader.ReadString().zParseEnum <ThemeFontValues>(ignoreCase: true);
                    break;

                case "hint":
                    if (bsonType == BsonType.Null)
                    {
                        break;
                    }
                    if (bsonType != BsonType.String)
                    {
                        throw new PBException($"wrong RunFonts Hint value {bsonType}");
                    }
                    value.Hint = bsonReader.ReadString().zParseEnum <FontTypeHintValues>(ignoreCase: true);
                    break;

                default:
                    throw new PBException($"unknow PageSize value \"{name}\"");
                }
            }
            bsonReader.ReadEndDocument();
            return(value);
        }
        // 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 stack = new Stack();
                    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);
                        stack.Push(element);
                    }
                    bsonReader.ReadEndArray();
                    return stack;
                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);
            }
        }