// public methods /// <summary> /// Applies a modification to the member map. /// </summary> /// <param name="memberMap">The member map.</param> public virtual void Apply(BsonMemberMap memberMap) { var memberSerializer = memberMap.GetSerializer(memberMap.MemberType); var memberSerializationOptions = memberMap.SerializationOptions; if (memberSerializationOptions == null) { var memberDefaultSerializationOptions = memberSerializer.GetDefaultSerializationOptions(); if (memberDefaultSerializationOptions == null) { var message = string.Format( "A serialization options attribute of type {0} cannot be used when the serializer is of type {1}.", BsonUtils.GetFriendlyTypeName(this.GetType()), BsonUtils.GetFriendlyTypeName(memberSerializer.GetType())); throw new NotSupportedException(message); } memberSerializationOptions = memberDefaultSerializationOptions.Clone(); memberMap.SetSerializationOptions(memberSerializationOptions); } memberSerializationOptions.ApplyAttribute(memberSerializer, this); }
private void DeserializeMember(BsonReader bsonReader, object obj, BsonMemberMap memberMap) { try { object value; var nominalType = memberMap.MemberType; var bsonType = bsonReader.GetCurrentBsonType(); if (bsonType == BsonType.Null && nominalType.IsInterface) { bsonReader.ReadNull(); value = null; } else { Type actualType; if (bsonType == BsonType.Null) { actualType = nominalType; } else { var discriminatorConvention = memberMap.GetDiscriminatorConvention(); actualType = discriminatorConvention.GetActualType(bsonReader, nominalType); // returns nominalType if no discriminator found } var serializer = memberMap.GetSerializer(actualType); value = serializer.Deserialize(bsonReader, nominalType, actualType, memberMap.SerializationOptions); } memberMap.Setter(obj, value); } catch (Exception ex) { var message = string.Format( "An error occurred while deserializing the {0} {1} of class {2}: {3}", // terminating period provided by nested message memberMap.MemberName, (memberMap.MemberInfo.MemberType == MemberTypes.Field) ? "field" : "property", obj.GetType().FullName, ex.Message); throw new FileFormatException(message, ex); } }
private void SerializeMember(BsonWriter bsonWriter, object obj, BsonMemberMap memberMap) { var value = memberMap.Getter(obj); if (!memberMap.ShouldSerialize(obj, value)) { return; // don't serialize member } bsonWriter.WriteName(memberMap.ElementName); var nominalType = memberMap.MemberType; if (value == null && nominalType.IsInterface) { bsonWriter.WriteNull(); } else { var actualType = (value == null) ? nominalType : value.GetType(); var serializer = memberMap.GetSerializer(actualType); serializer.Serialize(bsonWriter, nominalType, value, memberMap.SerializationOptions); } }
private void DeserializeExtraElement( BsonReader bsonReader, object obj, string elementName, BsonMemberMap extraElementsMemberMap) { if (extraElementsMemberMap.MemberType == typeof(BsonDocument)) { var extraElements = (BsonDocument)extraElementsMemberMap.Getter(obj); if (extraElements == null) { extraElements = new BsonDocument(); extraElementsMemberMap.Setter(obj, extraElements); } var bsonValue = (BsonValue)BsonValueSerializer.Instance.Deserialize(bsonReader, typeof(BsonValue), null); extraElements[elementName] = bsonValue; } else { var extraElements = (IDictionary <string, object>)extraElementsMemberMap.Getter(obj); if (extraElements == null) { if (extraElementsMemberMap.MemberType == typeof(IDictionary <string, object>)) { extraElements = new Dictionary <string, object>(); } else { extraElements = (IDictionary <string, object>)Activator.CreateInstance(extraElementsMemberMap.MemberType); } extraElementsMemberMap.Setter(obj, extraElements); } var bsonValue = (BsonValue)BsonValueSerializer.Instance.Deserialize(bsonReader, typeof(BsonValue), null); extraElements[elementName] = BsonTypeMapper.MapToDotNetValue(bsonValue); } }
/// <summary> /// Serializes an object to a BsonWriter. /// </summary> /// <param name="bsonWriter">The BsonWriter.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="value">The object.</param> /// <param name="options">The serialization options.</param> public void Serialize( BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { if (value == null) { bsonWriter.WriteNull(); } else { // Nullable types are weird because they get boxed as their underlying value type // we can best handle that by switching the nominalType to the underlying value type // (so VerifyNominalType doesn't fail and we don't get an unnecessary discriminator) if (nominalType.IsGenericType && nominalType.GetGenericTypeDefinition() == typeof(Nullable <>)) { nominalType = nominalType.GetGenericArguments()[0]; } VerifyNominalType(nominalType); var actualType = (value == null) ? nominalType : value.GetType(); if (actualType != _classMap.ClassType) { var message = string.Format("BsonClassMapSerializer.Serialize for type {0} was called with actualType {1}.", BsonUtils.GetFriendlyTypeName(_classMap.ClassType), BsonUtils.GetFriendlyTypeName(actualType)); throw new BsonSerializationException(message); } var documentSerializationOptions = (options ?? DocumentSerializationOptions.Defaults) as DocumentSerializationOptions; if (documentSerializationOptions == null) { var message = string.Format( "Serializer BsonClassMapSerializer expected serialization options of type {0}, not {1}.", BsonUtils.GetFriendlyTypeName(typeof(DocumentSerializationOptions)), BsonUtils.GetFriendlyTypeName(options.GetType())); throw new BsonSerializationException(message); } bsonWriter.WriteStartDocument(); BsonMemberMap idMemberMap = null; if (documentSerializationOptions.SerializeIdFirst) { idMemberMap = _classMap.IdMemberMap; if (idMemberMap != null) { SerializeMember(bsonWriter, value, idMemberMap); } } if (actualType != nominalType || _classMap.DiscriminatorIsRequired || _classMap.HasRootClass) { // never write out a discriminator for an anonymous class if (!_classMap.IsAnonymous) { var discriminatorConvention = _classMap.GetDiscriminatorConvention(); var discriminator = discriminatorConvention.GetDiscriminator(nominalType, actualType); if (discriminator != null) { bsonWriter.WriteName(discriminatorConvention.ElementName); BsonValueSerializer.Instance.Serialize(bsonWriter, typeof(BsonValue), discriminator, null); } } } var allMemberMaps = _classMap.AllMemberMaps; var extraElementsMemberMapIndex = _classMap.ExtraElementsMemberMapIndex; for (var memberMapIndex = 0; memberMapIndex < allMemberMaps.Count; ++memberMapIndex) { var memberMap = allMemberMaps[memberMapIndex]; // note: if serializeIdFirst is false then idMemberMap will be null (so no property will be skipped) if (memberMap != idMemberMap) { if (memberMapIndex != extraElementsMemberMapIndex) { SerializeMember(bsonWriter, value, memberMap); } else { SerializeExtraElements(bsonWriter, value, memberMap); } } } bsonWriter.WriteEndDocument(); } }
private void SerializeExtraElements(BsonWriter bsonWriter, object obj, BsonMemberMap extraElementsMemberMap) { var extraElements = extraElementsMemberMap.Getter(obj); if (extraElements != null) { if (extraElementsMemberMap.MemberType == typeof(BsonDocument)) { var bsonDocument = (BsonDocument)extraElements; foreach (var element in bsonDocument) { bsonWriter.WriteName(element.Name); BsonValueSerializer.Instance.Serialize(bsonWriter, typeof(BsonValue), element.Value, null); } } else { var dictionary = (IDictionary<string, object>)extraElements; foreach (var key in dictionary.Keys) { bsonWriter.WriteName(key); var value = dictionary[key]; if (value == null) { bsonWriter.WriteNull(); } else { var bsonValue = BsonTypeMapper.MapToBsonValue(dictionary[key]); BsonValueSerializer.Instance.Serialize(bsonWriter, typeof(BsonValue), bsonValue, null); } } } } }
private object DeserializeMemberValue(BsonReader bsonReader, BsonMemberMap memberMap) { try { var nominalType = memberMap.MemberType; var bsonType = bsonReader.GetCurrentBsonType(); if (bsonType == BsonType.Null && nominalType.IsInterface) { bsonReader.ReadNull(); return null; } Type actualType; if (bsonType == BsonType.Null) { actualType = nominalType; } else { var discriminatorConvention = memberMap.GetDiscriminatorConvention(); actualType = discriminatorConvention.GetActualType(bsonReader, nominalType); // returns nominalType if no discriminator found } var serializer = memberMap.GetSerializer(actualType); return serializer.Deserialize(bsonReader, nominalType, actualType, memberMap.SerializationOptions); } catch (Exception ex) { var message = string.Format( "An error occurred while deserializing the {0} {1} of class {2}: {3}", // terminating period provided by nested message memberMap.MemberName, (memberMap.MemberInfo.MemberType == MemberTypes.Field) ? "field" : "property", memberMap.ClassMap.ClassType.FullName, ex.Message); throw new FileFormatException(message, ex); } }
private void DeserializeExtraElement( BsonReader bsonReader, object obj, string elementName, BsonMemberMap extraElementsMemberMap) { if (extraElementsMemberMap.MemberType == typeof(BsonDocument)) { var extraElements = (BsonDocument)extraElementsMemberMap.Getter(obj); if (extraElements == null) { extraElements = new BsonDocument(); extraElementsMemberMap.Setter(obj, extraElements); } var bsonValue = (BsonValue)BsonValueSerializer.Instance.Deserialize(bsonReader, typeof(BsonValue), null); extraElements[elementName] = bsonValue; } else { var extraElements = (IDictionary<string, object>)extraElementsMemberMap.Getter(obj); if (extraElements == null) { if (extraElementsMemberMap.MemberType == typeof(IDictionary<string, object>)) { extraElements = new Dictionary<string, object>(); } else { extraElements = (IDictionary<string, object>)Activator.CreateInstance(extraElementsMemberMap.MemberType); } extraElementsMemberMap.Setter(obj, extraElements); } var bsonValue = (BsonValue)BsonValueSerializer.Instance.Deserialize(bsonReader, typeof(BsonValue), null); extraElements[elementName] = BsonTypeMapper.MapToDotNetValue(bsonValue); } }