/// <summary> /// Serializes an object to a BsonWriter. /// </summary> /// <param name="bsonWriter">The BsonWriter.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="value">The object.</param> /// <param name="options">The serialization options.</param> public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { if (value == null) { bsonWriter.WriteNull(); } else { if (nominalType == typeof(object)) { var actualType = value.GetType(); bsonWriter.WriteStartDocument(); bsonWriter.WriteString("_t", TypeNameDiscriminator.GetDiscriminator(actualType)); bsonWriter.WriteName("_v"); Serialize(bsonWriter, actualType, value, options); // recursive call replacing nominalType with actualType bsonWriter.WriteEndDocument(); return; } var dictionary = (IDictionary)value; var dictionarySerializationOptions = EnsureSerializationOptions(options); var dictionaryRepresentation = dictionarySerializationOptions.Representation; var keyValuePairSerializationOptions = dictionarySerializationOptions.KeyValuePairSerializationOptions; if (dictionaryRepresentation == DictionaryRepresentation.Dynamic) { dictionaryRepresentation = DictionaryRepresentation.Document; foreach (object key in dictionary.Keys) { var name = key as string; // check for null and type string at the same time if (name == null || name[0] == '$' || name.IndexOf('.') != -1) { dictionaryRepresentation = DictionaryRepresentation.ArrayOfArrays; break; } } } switch (dictionaryRepresentation) { case DictionaryRepresentation.Document: bsonWriter.WriteStartDocument(); foreach (DictionaryEntry dictionaryEntry in dictionary) { bsonWriter.WriteName((string)dictionaryEntry.Key); BsonSerializer.Serialize(bsonWriter, typeof(object), dictionaryEntry.Value, keyValuePairSerializationOptions.ValueSerializationOptions); } bsonWriter.WriteEndDocument(); break; case DictionaryRepresentation.ArrayOfArrays: case DictionaryRepresentation.ArrayOfDocuments: // override KeyValuePair representation if necessary var keyValuePairRepresentation = (dictionaryRepresentation == DictionaryRepresentation.ArrayOfArrays) ? BsonType.Array : BsonType.Document; if (keyValuePairSerializationOptions.Representation != keyValuePairRepresentation) { keyValuePairSerializationOptions = new KeyValuePairSerializationOptions( keyValuePairRepresentation, keyValuePairSerializationOptions.KeySerializationOptions, keyValuePairSerializationOptions.ValueSerializationOptions); } bsonWriter.WriteStartArray(); foreach (DictionaryEntry dictionaryEntry in dictionary) { var keyValuePair = new KeyValuePair<object, object>(dictionaryEntry.Key, dictionaryEntry.Value); _keyValuePairSerializer.Serialize( bsonWriter, typeof(KeyValuePair<object, object>), keyValuePair, keyValuePairSerializationOptions); } bsonWriter.WriteEndArray(); break; default: var message = string.Format("'{0}' is not a valid IDictionary representation.", dictionaryRepresentation); throw new BsonSerializationException(message); } } }
private 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 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); } }
/// <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(); } }
/// <summary> /// Serializes an object to a BsonWriter. /// </summary> /// <param name="bsonWriter">The BsonWriter.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="value">The object.</param> /// <param name="options">The serialization options.</param> public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { if (value == null) { throw new ArgumentNullException("value"); } // could get here with a BsonDocumentWrapper from BsonValueSerializer switch statement var wrapper = value as BsonDocumentWrapper; if (wrapper != null) { BsonDocumentWrapperSerializer.Instance.Serialize(bsonWriter, nominalType, value, null); return; } var rawBsonDocument = value as RawBsonDocument; if (rawBsonDocument != null) { RawBsonDocumentSerializer.Instance.Serialize(bsonWriter, nominalType, value, options); return; } var bsonDocument = (BsonDocument)value; var documentSerializationOptions = (options ?? DocumentSerializationOptions.Defaults) as DocumentSerializationOptions; if (documentSerializationOptions == null) { var 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); } bsonWriter.WriteStartDocument(); BsonElement idElement = null; if (documentSerializationOptions.SerializeIdFirst && bsonDocument.TryGetElement("_id", out idElement)) { bsonWriter.WriteName(idElement.Name); BsonValueSerializer.Instance.Serialize(bsonWriter, typeof(BsonValue), idElement.Value, null); } foreach (var element in bsonDocument) { // if serializeIdFirst is false then idElement will be null and no elements will be skipped if (!object.ReferenceEquals(element, idElement)) { bsonWriter.WriteName(element.Name); BsonValueSerializer.Instance.Serialize(bsonWriter, typeof(BsonValue), element.Value, null); } } bsonWriter.WriteEndDocument(); }
/// <summary> /// Serializes an object to a BsonWriter. /// </summary> /// <param name="bsonWriter">The BsonWriter.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="value">The object.</param> /// <param name="options">The serialization options.</param> public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { if (value == null) { bsonWriter.WriteNull(); } else { var actualType = value.GetType(); var discriminator = GetDiscriminator(nominalType, actualType); if (discriminator != null) { bsonWriter.WriteStartDocument(); bsonWriter.WriteString("_t", discriminator); bsonWriter.WriteName("_v"); Serialize(bsonWriter, actualType, value, options); bsonWriter.WriteEndDocument(); return; } var arraySerializationOptions = EnsureSerializationOptions<ArraySerializationOptions>(options); var itemSerializationOptions = arraySerializationOptions.ItemSerializationOptions; Type lastItemType = null; IBsonSerializer lastItemSerializer = null; bsonWriter.WriteStartArray(); foreach (var item in EnumerateItemsInSerializationOrder(value)) { var itemType = (item == null) ? typeof(object) : item.GetType(); IBsonSerializer itemSerializer; if (itemType == lastItemType) { itemSerializer = lastItemSerializer; } else { itemSerializer = BsonSerializer.LookupSerializer(itemType); lastItemType = itemType; lastItemSerializer = itemSerializer; } itemSerializer.Serialize(bsonWriter, typeof(object), item, itemSerializationOptions); } bsonWriter.WriteEndArray(); } }
/// <summary> /// Serializes an object to a BsonWriter. /// </summary> /// <param name="bsonWriter">The BsonWriter.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="value">The object.</param> /// <param name="options">The serialization options.</param> public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { if (value == null) { bsonWriter.WriteNull(); } else { if (nominalType == typeof(object)) { var actualType = value.GetType(); bsonWriter.WriteStartDocument(); bsonWriter.WriteString("_t", TypeNameDiscriminator.GetDiscriminator(actualType)); bsonWriter.WriteName("_v"); Serialize(bsonWriter, actualType, value, options); bsonWriter.WriteEndDocument(); return; } var items = ((Stack)value).ToArray(); // convert to array to allow efficient access in reverse order var arraySerializationOptions = EnsureSerializationOptions<ArraySerializationOptions>(options); var itemSerializationOptions = arraySerializationOptions.ItemSerializationOptions; // serialize first pushed item first (reverse of enumeration order) bsonWriter.WriteStartArray(); for (var i = items.Length - 1; i >= 0; i--) { BsonSerializer.Serialize(bsonWriter, typeof(object), items[i], itemSerializationOptions); } bsonWriter.WriteEndArray(); } }
/// <summary> /// Serializes an object to a BsonWriter. /// </summary> /// <param name="bsonWriter">The BsonWriter.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="value">The object.</param> /// <param name="options">The serialization options.</param> public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { if (value == null) { bsonWriter.WriteNull(); } else { if (nominalType == typeof(object)) { var actualType = value.GetType(); bsonWriter.WriteStartDocument(); bsonWriter.WriteString("_t", TypeNameDiscriminator.GetDiscriminator(actualType)); bsonWriter.WriteName("_v"); Serialize(bsonWriter, actualType, value, options); bsonWriter.WriteEndDocument(); return; } var items = (Queue)value; var arraySerializationOptions = EnsureSerializationOptions<ArraySerializationOptions>(options); var itemSerializationOptions = arraySerializationOptions.ItemSerializationOptions; bsonWriter.WriteStartArray(); foreach (var item in items) { BsonSerializer.Serialize(bsonWriter, typeof(object), item, itemSerializationOptions); } bsonWriter.WriteEndArray(); } }