public BsonMemberMap GetMemberMapForElement(string elementName) { // linear search should be fast because elements will normally be in the same order as the member maps for (int i = _from; i <= _to; i++) { var memberMap = _memberMaps[i]; if (memberMap == null) { if (i == _from) { _from++; // shrink the range from the left } continue; } if (memberMap.ElementName == elementName) { if (i == _from) { _from++; // shrink the range from the left } else if (i == _to) { _to--; // shrink the range from the right } else { _memberMaps[i] = null; // set to null so we don't think it's missing } return(memberMap); } } // fall back to the class map in case it's a duplicate element name that we've already null'ed out // but make sure not to return the extraElementsMemberMap if (_extraElementsMemberMap == null || elementName != _extraElementsMemberMap.ElementName) { return(_classMap.GetMemberMapForElement(elementName)); } else { return(null); } }
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); } }